Pytanie:
Technika bezstratnej kompresji sygnałów cyfrowych w systemie wbudowanym
toasty
2020-07-29 02:24:07 UTC
view on stackexchange narkive permalink

Oto scenariusz:

Mam wbudowany system, w którym ADC rejestruje próbkę 16-bitowego potencjostatu co 2 sekundy.System kontynuuje rejestrowanie danych przez tygodnie, co sprawia, że użycie pamięci jest problemem.

Zamiast wykorzystywać 16-bitową pamięć dla każdej z milionów próbek, jak mogę bezstratnie skompresować sygnał, gdy jest rejestrowany?Idealnie chciałbym rozbić sygnał na 15-minutowe skompresowane segmenty.Jestem pewien, że istnieje na to standard, ale nie mogę go znaleźć.

Jeśli to pomoże, sygnał będzie miał najczęściej bardzo małe delty między próbkami (niska częstotliwość).

Czy przechowujesz surowe wartości ADC, czy przekonwertowane wartości (zmiennoprzecinkowe pojedynczej / podwójnej precyzji)?Znacznik czasu?Czy przechowujesz je w pamięci flash lub RAM?
Obecnie buforuję 450 surowych próbek w pamięci RAM, a następnie przechowuję wszystkie 450 próbek w pamięci flash z sygnaturą czasową.
@toasty Podaj nam więcej szczegółów na temat tych próbek.Naprawdę pomocne pomysły na temat kompresji będą wymagały bardzo szczegółowego zrozumienia tego, z czym masz do czynienia.Na przykład, jeśli są to dane z wydarzenia o rozkładzie wykładniczym z pewnym rodzajem szumu, pewne pomysły będą preferowane.Tak jest.Im więcej wiemy, tym lepszą odpowiedź możesz uzyskać.
To potencjostat.
i musi obsługiwać wiele analitów
Byłbym mocno kuszony, aby użyć karty SD (mikro lub nie).Najmniejszy, jaki możesz kupić, to około 16G lub 32G, który pomieści próbki o wartości około 544 lub 1088 lat przy 2 bajtach 0,5 sps, nie licząc narzutu systemu plików.Jeśli zaimplementujesz zgodny system plików, można go przesłać do komputera w celu analizy.
Karta SD jest poza zakresem projektu :)
Sprawdzenie rzeczywistości: „używanie karty SD” jest poza zakresem twojego projektu, ale „opracowanie nowej, niestandardowej techniki bezstratnej kompresji danych” nie jest takie ???Zdajesz sobie sprawę, że jeśli jest * w ogóle * wartość * przypisywana Twojemu czasowi, ekonomia jest tutaj całkowicie wsteczna.Jeśli nie jest to projekt z czystej pasji, nie rób tego.
Czy faktycznie masz 16-bitową dokładność?Jeśli niższe 4 bity są zwykłym szumem, nie ma sensu ich rejestrować.
Możesz kupić kartę SD i czytnik za <20 USD, który może pomieścić wiele gigabajtów danych.Jeśli używasz Arduino, istnieją nawet biblioteki, które wykonają za Ciebie wszystkie protokoły i systemy plików, więc możesz je po prostu podłączyć i nakazać zapisywanie danych.
Witamy!„Wbudowany” może oznaczać tak szeroki zakres możliwości ... Zakładam, że ten system nie może obsługiwać Linuksa lub równoważnego systemu operacyjnego, który dałby zip, lzma itp. Jako łatwą odpowiedź.Jeśli użycie karty SD jest poza zakresem, pomocne byłoby, gdybyśmy wiedzieli nieco więcej o możliwościach twojego systemu.Opracowanie takiego rozwiązania to kompromis, ale nie możemy wiele pomóc, jeśli nie wiemy, co próbujesz zrównoważyć.Żywotność baterii?Koszt?Fizyczny rozmiar?Ile próbek będziesz musiał przechowywać?
Projekt fizyczny i elektryczny jest stały i dlatego nie można go rozszerzyć.Jest to system zasilany bateryjnie z mikrokontrolerem działającym w trybie bare-metal.Gdybym potrzebował pomocy w zaprojektowaniu systemu i wyborze komponentów, poprosiłbym o to zamiast tego.Byłem ciekawy, jakie rozwiązania kompresji sygnału istnieją, a odpowiedzi były jak dotąd trafne i bardzo pomocne.
Kompresja bezstratna to modelowanie statystyczne, a nie dostarczyłeś zbyt wiele modelu.Z tego, co nam powiedziałeś, nie możesz zrobić nic lepszego niż kodowanie delt przez Huffmana.Niezależnie od tego, potencjostat wydaje się być dość hałaśliwym urządzeniem, a szumu nie można skompresować, więc wyobrażam sobie, że uzyskasz kompresję w najlepszym przypadku 2: 1.
@toasty „Wspaniałą rzeczą w standardach jest to, że jest ich tak wiele do wyboru”.
Sześć odpowiedzi:
Dave Tweed
2020-07-29 03:47:03 UTC
view on stackexchange narkive permalink

Kompresja polega na znajdowaniu nadmiarowości w danych i ich usuwaniu. Ponieważ wydaje się, że nie jesteś w stanie powiedzieć nam zbyt wiele o swoich rzeczywistych zestawach danych, ta odpowiedź będzie musiała być bardzo ogólna.

Rozumiem, że dane „potencjostatu” są ciągłe, ogólnie zmieniają się powoli, ale mogą wykazywać niewielkie odchylenia od próbki do próbki. Dobrym sposobem na zakodowanie tego w 15-minutowych (450 przykładowych) blokach byłoby dopasowanie pierwszego, drugiego lub trzeciego rzędu (lub więcej, w zależności od ogólnej natury danych) wielomian do bloku danych, aby uchwycić jego ogólny kształt. 1

Blok zostałby następnie zakodowany jako parametry tego wielomianu (być może cztery liczby 16-bitowe) plus indywidualne odchylenia próbki od tego wielomianu, które przypuszczalnie mogą być znacznie mniejsze - być może 450 liczb 3- lub 4-bitowych , co daje łącznie 1414 lub 1864 bitów zamiast oryginalnych 7200 bitów - współczynnik kompresji w przybliżeniu 4 lub 5 do 1.

Jeśli okaże się, że nie możesz użyć stałej szerokości dla przykładowych delt, rozważ użycie kodowania Huffmana do ich przedstawienia - małe wartości dają krótkie kody, podczas gdy przypuszczalnie rzadsze duże wartości dają dłuższe kody . Nadal powinieneś być w stanie uzyskać współczynnik kompresji około 3 do 1, znowu w zależności od danych.


1 Jeśli okaże się, że dane mają składnik cykliczny, bardziej przydatne może być zastosowanie autoregresji lub analizy Fouriera do identyfikacji kluczowych składowych okresowych (częstotliwości, fazy i amplitudy), a następnie zapisz delty poszczególnych próbek z funkcji zdefiniowanej przez te parametry.

jpa
2020-07-29 12:56:21 UTC
view on stackexchange narkive permalink

Twoje dane będą prawdopodobnie składać się z dwóch składników:

  • Niska prędkość zmian rzeczywistego napięcia
  • Losowe odchylenie spowodowane szumem ADC

Jest prawdopodobne, że losowe odchylenie przedstawi większość entropii danych. Możesz to zmniejszyć przez nadpróbkowanie: na przykład pobranie 4 próbek na raz i podzielenie wyniku przez 4 zmniejszyłoby szum o połowę.

Nie ma szeroko popularnego formatu kompresji bezstratnej kompresji próbek ADC. Czasami używany jest bezpłatny bezstratny kodek audio, ale jest on dość obciążony obliczeniowo i może nie być odpowiedni dla twojego systemu. Typowe bezstratne formaty kompresji, takie jak DEFLATE i LZ4, zajmują mniej zasobów obliczeniowych, ale współczynnik kompresji nie będzie zbyt dobry, chyba że dodasz niestandardowe kroki przetwarzania wstępnego. Dlatego najlepiej byłoby zaprojektować własny schemat kompresji.

Ogólna struktura metod kompresji zwykle składa się z dwóch części:

  1. Przetwarzanie wstępne w celu poprawy ściśliwości: na przykład pobranie różnicy dwóch kolejnych wartości lub zastosowanie predykcji wielomianowej.
  2. Kodowanie entropii do reprezentowania każdego symbolu z najmniejszą potrzebną liczbą bitów. Jedną z powszechnych metod jest kody Huffmana, wykorzystujące tabele stałe lub dynamiczne.

Jednym z niestandardowych formatów, których użyłem z powodzeniem, jest obliczenie różnicy między kolejnymi próbkami i zakodowanie różnicy za pomocą kodowania gamma Elias. Ma tę zaletę, że jest prosty w implementacji i pozwala na kodowanie mniej niż 1 bajta na próbkę dla wolno zmieniających się sygnałów.

Glenn Willen
2020-07-29 11:51:13 UTC
view on stackexchange narkive permalink

Najlepsze kodowanie będzie w dużej mierze zależeć od dystrybucji próbek. Powiedziałeś nam, że delty są w większości dość małe, co oznacza, że ​​pierwszym krokiem będzie prawie na pewno kodowanie delta (przekształcenie każdej wartości w jej różnicę w stosunku do poprzedniej wartości).

Kolejnym ograniczeniem będzie system, w którym wykonujesz kodowanie - powiedziałeś, że jest „osadzony”, ale obejmuje to całkiem szeroki zakres możliwości. Powiedziałeś również, że karty SD są poza zakresem i że buforujesz tylko 450 próbek naraz w pamięci RAM, co sugeruje naprawdę bardzo mały system. W takim przypadku optymalizacja pod kątem prostoty i oszczędzania procesora / pamięci RAM wydaje się odpowiednia.

Jeśli najczęstszą wartością delta jest dokładnie 0 - to znaczy, że partie próbek są takie same jak poprzednia próbka - prawdopodobnie dobrym pomysłem jest najpierw „zakodowanie długości serii” te serie wartości 0. (Tj. Po prostu zapisywanie, ile było ich w rzędzie.)

Reszta zależy dalej od tego, jak wygląda rozkład wartości. Zakładam dla celów ćwiczeń, że prawie wszystkie są w zakresie -64 < x < 63 (tj. 7-bitowa liczba całkowita ze znakiem). Zakładam również, że najłatwiej jest pracować z bajtami, a nie bitami (co prawdopodobnie jest prawdą, jeśli np. Piszesz C) - jeśli to nie jest prawda, zobacz sam dół odpowiedzi dla schematu bitowego. Bardzo proste kodowanie bajtowe mogłoby wyglądać mniej więcej tak:

0b0xxxxxxx - wartość literału (delta) reprezentowana jako 7-bitowa liczba całkowita ze znakiem w części „xxxxxxx”. (Wartości od -64 do 63.)

0b10xxxxxx - ciąg zer (delt) o długości reprezentowanej przez "xxxxxx" (6 bitów bez znaku może wyrazić do 63, a jeśli potrzebujemy więcej, możemy po prostu dodać kolejny wpis.)

0b110xxxxx 0byyyyyyyy - wartość literału (delta) reprezentowana jako 13-bitowa liczba całkowita ze znakiem w części „xxxxxyyyyyyyy”.

0b11111111 0bxxxxxxxx 0byyyyyyyy - wartość literału (delta) reprezentowana jako 16-bitowa liczba całkowita ze znakiem. Jest to bardzo nieefektywne kodowanie (oczywiście), ponieważ zamienia 16-bitową wartość na 3-bajtową reprezentację. To niepotrzebnie marnuje miejsce, aby utrzymać wyrównanie bajtów wyjściowych. Ten schemat ma sens tylko wtedy, gdy tak duże delty są bardzo rzadkie. (Każdy nietrywialny schemat kompresji będzie miał pewne dane wejściowe, dla których wynikowe wyjście jest faktycznie większe; to jest twierdzenie teorii informacji.)

(Powyższy schemat jest nieco inspirowany kodowaniem UTF-8 w Unicode.)

W przeciwieństwie do kodów Huffmana (wymienionych w innej odpowiedzi), zakładany rozkład wartości jest ustalany z góry. Jest to zaleta, ponieważ sprawia, że ​​wszystko jest proste i pozwala uniknąć dodawania narzutu na początku każdego bloku sampli; to wada, ponieważ bardziej adaptacyjny schemat nie wymagałby ręcznego dostrajania dystrybucji.

Jeśli delty znacznie mniejsze niż -64 do 63 są powszechne, lepsze kodowanie bajtowe niż powyższe będzie wymagało przetworzenia więcej niż jednej próbki na raz, aby uzyskać kompresję lepszą niż 2: 1 (to znaczy więcej niż jedna próbka na bajt wyjściowy.)

Jeśli kodowanie bitowe jest w porządku, znacznie prostszy do opisania schemat jest następujący: nadal najpierw kodowanie delta, a następnie kodowanie w następujący sposób. Po bitu 0 następuje dodatnia liczba całkowita o zmiennej długości, kodująca liczbę następnych zer; po bitu 1 następuje bit znaku, a następnie dodatnia liczba całkowita o zmiennej długości, razem kodując następną wartość (delta). Dodatnie liczby całkowite o zmiennej długości mogą być zakodowane przy użyciu jednego z kodów z https://en.wikipedia.org/wiki/Universal_code_(data_compression), takiego jak jeden z kodów Eliasa. (To, które kodowanie jest najlepsze, znowu będzie zależeć od dystrybucji danych, ale prawdopodobnie każde z nich będzie świetne).

Sposób, w jaki przerwałeś swój proces myślowy, jest niezwykle pomocny.Dziękuję Ci!
@toasty Nie ma za co, cieszę się, że to było pomocne!
Uwaga: Kilka innych osób skomentowało, że losowy szum ADC zostanie nałożony na próbki, co spowoduje losowe wahania między każdą próbką.Jeśli to prawda (chyba że chcesz najpierw odfiltrować szum, przed kompresją, co spowodowałoby stratę), opisywane przeze mnie kodowanie długości serii nie ma sensu, ponieważ w obecności szumu, który zmienia każdą próbkę, nie ma sensuto nigdy nie pomoże.
Vegard
2020-07-29 11:29:47 UTC
view on stackexchange narkive permalink

Aby rozwinąć pomysł Dave'a, innym sposobem na przechowywanie 15-minutowego fragmentu, jeśli wartość zmienia się powoli w czasie, jest przechowywanie tylko zmian.

Zacząłbyś od pełnej 16-bitowej liczby, a następnie określasz, ile bitów potrzebujesz, aby zapisać największą zmianę między dwoma próbkami.Na przykład, jeśli największa zmiana przechodzi z 1050 do 1013, różnica wynosi -37 lub 1011011 w układzie dwójkowym komplementarnym.To zajmuje 7 bajtów na próbkę zamiast 16.

Oczywiście ogranicza to możliwość rejestrowania skoków temperatury.Możesz dodać trochę, który mówi ci, abyś wziął następne 16 bitów i zinterpretował je jako pełną próbkę (w przypadku dużych zmian) lub tylko pobrał następne n bitów i zinterpretował je jako delta.
Michael
2020-07-29 15:46:52 UTC
view on stackexchange narkive permalink

Nie zapisuj danych co dwie sekundy

Zapisuj dane tylko wtedy, gdy zmiana przekracza określony próg, i dołącz sygnaturę czasową.

Zarówno w przypadku danych, jak i sygnatury czasowej można rejestrować delty (różnicę w stosunku do poprzedniej próbki) z mniejszą liczbą bitów i używać pełnej szerokości tylko wtedy, gdy zmiana przekracza szerokość zdefiniowaną dla delt.

Brian Drummond
2020-07-29 22:51:38 UTC
view on stackexchange narkive permalink

Na dwa sposoby:

  1. Utwórz własny schemat kompresji.Zacznij prosto: na przykład, jeśli kilka próbek z rzędu ma tę samą wartość, użyj kodowania RLL.Udoskonalenie programu może wymagać wysiłku badawczo-rozwojowego.Odpowiedzi Dave'a Tweeda i Glenna Willena sugerują dobre podejście.

  2. Wybierz istniejący schemat.Zgodnie z odpowiedzią jpa, FLAC natychmiast przychodzi na myśl (chociaż ma na celu częstotliwość próbkowania dźwięku).Jeśli masz dość mocny procesor i znajdziesz łatwą w użyciu bibliotekę oprogramowania, praca zostanie wykonana znacznie mniejszym wysiłkiem.

Jeśli nie interesuje Cię szum o wysokiej częstotliwości, filtr dolnoprzepustowy przed kompresją prawdopodobnie pomoże w obu przypadkach w poprawieniu współczynnika kompresji.



To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 4.0, w ramach której jest rozpowszechniana.
Loading...