Pisanie własnego kodu rozpoznawania głosu [zamknięte]


17

opis problemu

Chcę używać rozpoznawania głosu jako części projektu sprzętowego, który chciałbym być całkowicie samowystarczalny (używam małych urządzeń o niskiej mocy i niskiej prędkości, takich jak Arduino i Raspberry Pi, Kinects itp., Nie działający tradycyjny komputer z system operacyjny jest zaangażowany, więc projekt zamknięty / samowystarczalny).

Rozpoznawanie głosu może być bardzo skomplikowane w zależności od wymaganego poziomu zaawansowania. Mam, jak sądzę, stosunkowo prosty zestaw wymagań. Chcę tylko rozpoznać własny głos i mam mały słownik zawierający około 20 słów, które chciałbym rozpoznać. Dlatego nie wymagam skomplikowanych bibliotek rozpoznawania mowy i tekstu ani żadnego z doskonałych programów innych firm, które znajduję za pośrednictwem wyszukiwarek internetowych (nie brakuje ich!). Uważam, że moje wymagania są „na tyle proste” (w granicach rozsądku), że mogę napisać własne rozwiązanie. Zastanawiam się, czy ktoś napisał taki proces w ten sposób i czy moja metoda ma poważne wady? Czy istnieje lepszy sposób, aby to zrobić bez konieczności posiadania wysokiego poziomu matematyki lub konieczności pisania złożonego algorytmu? Oto rozwiązanie, które próbowałem wymyślić poniżej.

Opis rozwiązania

Będę pisać w C, ale chcę omówić proces agnostyczny języka, skupiając się na samym procesie. Więc zignorujmy to, jeśli możemy.

1. Zapamiętam wstępnie mój słownik słów, aby pasował do tych, które są wypowiadane. Możemy sobie wyobrazić, że mam 20 nagrań z 20 różnych słów, a może krótkie frazy lub zdania dwóch lub trzech słów. Uważam, że dzięki temu proces porównywania dwóch nagranych plików jest łatwiejszy niż faktyczna konwersja audio na tekst i porównywanie dwóch ciągów.

2) Mikrofon jest podłączony do mojego urządzenia sprzętowego obsługującego mój kod. [1] Kod stale pobiera próbki o stałej długości, na przykład 10 ms długości, i przechowuje na przykład 10 kolejnych próbek, w stylu rejestrowania cyklicznego. [2] (Wymyślam te liczby z góry mojej głowy, więc są to tylko przykłady opisujące ten proces).

[1] Prawdopodobnie byłoby to połączone przez filtr pasmowoprzepustowy i wzmacniacz operacyjny, podobnie jak w przypadku nagrań słownikowych, aby zminimalizować przechowywane i zebrane próbki audio.

[2] Nie jestem pewien, jak dokładnie wezmę próbkę, muszę jednak opracować metodę, jeśli stworzę liczbę liczbową (liczba całkowita / liczba zmiennoprzecinkowa / podwójna), która reprezentuje dźwięk próbki 10 ms (być może wartość CRC lub suma MD5 itp. próbki dźwięku) lub strumień liczb (być może strumień odczytów częstotliwości). Ostatecznie „próbka” będzie liczbą lub liczbami liczbowymi. Ta część będzie wymagała znacznie większego sprzętu, więc nie do dyskusji tutaj.

3) Kod sprawdza, czy jest przechowywanych 10 kolejnych próbek i szuka wzrostu głośności, aby wskazać wypowiedziane słowo lub frazę (przerwa od ciszy), a następnie zwiększa się, gdy kolejne próbki są zbierane, na przykład 500 próbek. Oznaczałoby to, że przechwytuje 5 sekund dźwięku w próbkach 10 ms.

To są te próbki lub „wycinki”, które są porównywane między dźwiękiem przechowywanym a dźwiękiem przechwyconym. Jeśli wystarczająco wysoki odsetek przechwyconych próbek pasuje do przechowywanych równoważnych, kod przyjmuje to samo słowo.

The start of a store recording of the world "hello" for example,
stored words are split into 10 msec samples also

Stored Sample No           | 1| 2| 3| 4| 5| 6| 7|  8|
Stored Sample Value        |27|38|41|16|59|77|200|78|

Incoming audio (me saying "hello") with some "blank" samples
at the start to symbolise silence

Incoming Sample No         | 1| 2| 3| 4| 5| 6| 7| 8| 9|10| 11|12|
Incoming Sample Value      |  |  |  |20|27|38|46|16|59|77|200|78|

4 Gdy kod zgromadzi pełny strumień próbek, następnie odcina próbki puste na początku, aby wygenerować następujące nagranie audio. Może również przesunąć zestaw próbek do tyłu i do przodu o kilka miejsc, aby lepiej dopasować do przechowywanej próbki.

To daje przykładowy zestaw jak poniżej:

Stored Sample No           | 1| 2| 3| 4| 5| 6|  7| 8|
Stored Sample Value        |27|38|41|16|59|77|200|78|

Incoming Sample No      |-1| 1| 2| 3| 4| 5| 6|  7| 8|
Incoming Sample Value   |20|27|38|46|16|59|81|201|78|

5 Uważam, że posiadając wartość procentową określającą, jak blisko musi być każda próbka, próbka 7 różni się wartością 1, która jest mniejsza niż% 1, oraz wartością procentową dla całkowitej liczby próbek, która musi mieścić się w procentach odpowiadających próbce , kod ma łatwo dostrojony poziom dokładności.

Nigdy wcześniej nie robiłem czegoś takiego z dźwiękiem, może to być dużo pracy. Dlatego zadaję to pytanie, jeśli być może znasz już odpowiedź na to pytanie, aby była oczywista (jakakolwiek może być ta odpowiedź). Mam nadzieję, że nie będzie to trudne obliczeniowo zadanie, ponieważ sprzęt, którego będę używał, będzie działał z małą sekundą. W setkach Megaherców (być może 1 Ghz za pomocą przetaktowanego Rasp Pi). Jest to więc dość prymitywny sposób dopasowania próbek audio przy użyciu niższej mocy obliczeniowej. Nie dążę do natychmiastowych rezultatów, ale mniej niż 30 sekund na przyzwoity dowód koncepcji.

PS Nie mam przedstawiciela, który oznaczyłby to nowym tagiem, takim jak „audio”, „rozpoznawanie dźwięku”, „głos”, „rozpoznawanie głosu” itp.


17
VR jest cholernie złożonym i wątpię, aby ktoś bez wiedzy w tej dziedzinie byłby w stanie zrobić znaczne postępy bez dużej ilości czytania. Pierwszą rzeczą, która uderza mnie w twoim algorytmie, jest to, że nie radzi sobie on z różnicami w szybkości wypowiadania słowa. Nawet prosta VR zajęła lata, aby wszystko było w porządku.
Gort the Robot

4
W rzeczy samej. Ty, chyba że masz na myśli lata rozwoju, możesz zajrzeć do bibliotek, które możesz skompilować do swojego celu. Jestem pewien, że istnieją.
rig

6
Sugerowałbym dodatkowy krok - wykonaj transformatę Fouriera dla każdej próbki. Daje to intensywność każdej częstotliwości dźwięku w czasie, zamiast bezpośrednio zajmować się próbkami. W przypadku samogłosek, które zwykle wypowiadasz, będzie dość spójna częstotliwość podstawowa, przy której można wykryć. Musisz przyjrzeć się konkretnym cechom mowy, a nie tylko dźwiękowi. Jak powiedzieli inni, jest to trudne zadanie.
Paul Anderson

1
Sugeruję, abyś spróbował pobawić się bibliotekami rozpoznającymi głos, nawet jeśli nie możesz ich użyć w produkcie końcowym. Przydałyby się przy tworzeniu dowodu koncepcji.
zapisano

Odpowiedzi:


3

Nie wierzę, że Arduino ma moc konia, aby to zrobić. działa przy 16 MHz An Arduino ma około 32 KB pamięci. Nawet 20 słów próbkowanych w formacie MP3 (mniejszych niż wav) nie zmieściłoby się w nim, mimo że jest to tylko twój własny głos.

Rasberi pi może załatwić sprawę, działa przy 700 MHz w zależności od wersji, w której może mieć 512 MB pamięci. To wciąż nie jest dużo ciasta.

Być może potrzebujesz Fouriera ( http://www.drdobbs.com/cpp/a-simple-and-efficient-fft-implementatio/199500857 )

Lub jeśli zamierzasz użyć woluminu, zrób kilka średnich z wcześniejszymi próbkami, takimi jak
x = (x + x [n-1] + x [n-2] + x [n-3]) / 4 // to całkiem proste może potrzeba więcej

Następną rzeczą, którą musisz zrobić, to pomyśleć, że jeśli chcesz wykreślić te wartości X, to potrzebujesz jakiegoś wykrycia nachylenia tej linii, ponieważ wykrywanie poleceń na podstawie objętości zależy w przeciwnym razie dużo od odległości, podczas gdy wolisz wykryć wzór słowa

Potem zależy nieco od tego, jak zarejestrować nachylenie, aby wzór pasował innym razem. Mam na myśli to, że nie mówi się dokładnie w tempie, które komputer może dopasować, a nachylenie może być nieco bardziej strome. W końcu wydaje mi się, że jest to trochę tak strome, że te linie i ich długość w osi y powinny mieścić się w pewnej średniej


1
  1. Arduino i Raspberry Pi to płytki prototypowe z niewielką ilością chipów. Najpierw powinieneś skupić się na chipie. Poszukaj czegoś z zestawem narzędzi DSP (cyfrowe przetwarzanie sygnałów), być może masz już zestaw narzędzi DSP i nie wiesz o tym. Przyborniki DSP mają na wywołanie algorytmy takie jak fft (szybka transformata Fouriera) i ifft (odwrotne fft) do szybkiej analizy w dziedzinie częstotliwości.

  2. Skoncentruj się na swoim stylu programowym: czy twoje próbki są w stosie czy w kolejce? Będziesz potrzebować kolejki dla tego typu danych. Kolejka wygląda następująco:

    Position NO --|1|2|3|4|5|6|7|8|
    Sample Value  |5|7|9|1|2|2|9|8|
    

    Następna iteracja:

    Position NO --|1|2|3|4|5|6|7|8|
    Sample Value  |0|5|7|9|1|2|2|9|
    ->  First in First out (FIFO)
    

    Zauważ, jak sprawy zmieniają się w kierunku „prawa”? Myślę, że opisałeś algorytm „kołowy”. Po prostu nadpisz najstarsze próbki drugimi najstarszymi próbkami, a następnie nadpisz drugie najstarsze próbki trzecią najstarszą próbką ... aż do początku kolejki, w której wstawiasz najnowsze dane.

  3. „Kod ciągle pobiera próbki o stałej długości, powiedzmy 10 ms” <- niepoprawny Pomyśl w ten sposób: Kod dyskretnie pobiera skwantowane (wysokościowe) próbki, z częstotliwością próbkowania 10000 próbek na sekundę, co czyni każdą próbkę 0,1 ms od siebie.

    Jaka jest twoja częstotliwość próbkowania? Jaka jest szybkość transmisji twojego kwantyzatora? Niższe liczby pomogą ci zwolnić pamięć. Sugerowałbym niską częstotliwość próbkowania, taką jak 6600 próbek na sekundę (Nyquist). Podejrzewam, że 4-bitowy (16 poziomów) byłby wystarczający do rozpoznania. To 3300 bajtów zapisu na sekundę. Teraz wykonaj fft i usuń wszystko powyżej 3300 Hz (filtr telefoniczny). Teraz masz 1650 bajtów używanych na jedną sekundę dźwięku. Te sztuczki DSP pozwolą zaoszczędzić dużo pamięci.

    Nie wiem, kto uważa, że ​​512 MB jest małe. Dzięki powyższym informacjom, które wynoszą ponad 300 000 sekund nagrywania ... trwają ponad 3 dni.

  4. Myślę, że znajdziesz domenę częstotliwości (za pomocą fft) jako lepsze środowisko do rozpoznawania głosu.

Mam nadzieję, że nie pomyliłem cię gorzej :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.