Wykorzystanie bezstratnego kodeka wideo do archiwizacji (monochromatycznych) naukowych danych wideo

9

Podstawowe pytanie: jaki jest odpowiedni kodek do przechowywania / archiwizowania naukowych danych wideo w sposób bezstratny ?

Próbuję pomóc mojej grupie badawczej w przechowywaniu / archiwizowaniu niektórych filmów nagranych pod mikroskopem. Te filmy (w skali szarości) są w nieskompresowanym (surowym wideo) formacie BGR24, 660 x 492 przy 61 klatkach na sekundę i zazwyczaj około 1 minuty. Moi koledzy z laboratorium oszaleli na punkcie rozmiaru tych plików (gigabajtów każdy). Zasugerowałem skompresowanie ich przy użyciu bezstratnego kodeka. (Potrzeba bezstratnej tutaj jest dlatego, że filmy są danymi naukowymi; stąd istnieje pewne niebezpieczeństwo, że utrata kodeku może zmienić treść w zły / nieoczekiwany sposób.)

Oto, co próbowałem. Najpierw złapałem pierwsze 10 sekund jednego z tych filmów i przekonwertowałem do formatu monochromatycznego (surowego) za pomocą FFMpeg.

ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv

Następnie próbowałem użyć bezstratnego trybu libx264 (poprzez ustawienie -crf 0) do skompresowania pliku wynikowego

ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv

Na koniec wyodrębniłem surowe dane YUV zarówno z plików raw, jak i h264 MKV i porównałem je.

ffmpeg -i raw-gray.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
ffmpeg -i x264-yuv420p.mkv -c:v rawvideo -pix_fmt gray x264-decompressed.yuv
diff -sq raw-gray.yuv x264-decompressed.yuv

Tutaj diffpolecenie informuje, że pliki różnią się, gdy spodziewałem się, że będą takie same. Dlaczego to? Czy to tylko niewielki błąd zaokrąglania, czy może coś tracę po wykonaniu kompresji H264 (podobno bezstratnej)? Następuje konwersja formatów pikseli ( gray (YUV400) <-> YUV420), ale kanały kolorów (UV) powinny być puste, ponieważ dane wejściowe są monochromatyczne.

Jeśli rzeczywiście coś tracę, czy jest coś, co mogę zrobić, aby to naprawić? Czy istnieje inny (bezstratny) kodek, który może być bardziej odpowiedni dla moich danych?


Aktualizacja 1 : Użyłem zrzutu heksadecymu do porównania zawartości nieskompresowanych danych YUV z raw-gray.yuv(nigdy nieskompresowanych) i x264-decompressed.yuv(skompresowanych, a następnie zdekompresowanych) bardziej szczegółowo. Oto kilka pierwszych bajtów.

[raw-gray.yuv]

00000000  4e 50 51 53 53 52 51 50  51 51 50 4f 50 50 50 50
00000010  51 51 50 51 52 53 51 51  52 52 53 53 52 51 51 53
00000020  51 53 54 55 53 51 52 54  53 53 52 50 51 50 52 52
00000030  51 52 51 51 51 52 54 52  52 52 51 51 51 53 57 58
00000040  57 57 55 54 54 52 53 51  51 52 53 55 55 54 53 53
00000050  51 51 52 52 53 52 51 50  50 50 50 51 51 4f 4f 4e
00000060  4c 4d 4e 4d 4f 50 4f 50  51 51 51 52 52 52 52 50
00000070  50 50 52 52 53 55 55 55  57 52 53 53 53 54 56 56

[x264-decompressed.yuv]

00000000  53 55 56 57 57 56 56 55  56 56 55 54 55 55 55 55
00000010  56 56 55 56 56 57 56 56  56 56 57 57 56 56 56 57
00000020  56 57 58 59 57 56 56 58  57 57 56 55 56 55 56 56
00000030  56 56 56 56 56 56 58 56  56 56 56 56 56 57 5b 5c
00000040  5b 5b 59 58 58 56 57 56  56 56 57 59 59 58 57 57
00000050  56 56 56 56 57 56 56 55  55 55 55 56 56 54 54 53
00000060  51 52 53 52 54 55 54 55  56 56 56 56 56 56 56 55
00000070  55 55 56 56 57 59 59 59  5b 56 57 57 57 58 5a 5a

Wartości z poprzedniego pliku są od 4 do 5 niższe niż wartości z drugiego. To samo można znaleźć, zagłębiając się nieco głębiej w plik.


Aktualizacja 2 : Jeśli używam libx264 w trybie RGB, mogę uzyskać dokładne dopasowanie do oryginału, robiąc to samo co powyżej, oprócz poniższych.

ffmpeg -i raw-gray.mkv -c:v libx264rgb -crf 0 -pix_fmt bgr24 x264-bgr24.mkv
ffmpeg -i x264-bgr24.mkv -c:v rawvideo -pix_fmt gray x264-bgr24-decomp.yuv
diff -sq raw-gray.yuv x264-bgr24-decomp.yuv

Ostatnie polecenie informuje, że dwa pliki są identyczne . Niestety x264-bgr24.mkvjest około 3 razy większy niż x264-yuv420.mkv, więc kompresja w trybie RGB nie jest tak dobra.

Czytałem gdzieś, że libx264 skutecznie kompresuje wideo w skali szarości w trybie YUV, ponieważ bierze pod uwagę fakt, że tylko kanał Y zawiera prawdziwe informacje (oba kanały U i V są zerowe dla wideo monochromatycznego). Uważam, że w trybie RGB wszystkie kanały zawierają identyczne informacje dla wejścia monochromatycznego. Może libx264rgb nie korzysta z tego.

Czy jest więc sposób na użycie trybu YUV bez zmiany wideo, ponieważ kompresja jest w ten sposób znacznie bardziej wydajna?


Aktualizacja 3 : Byłem w stanie rozwiązać problem z libx264, używając -pix_fmt yuvj420pzamiast -pix_fmt yuv420p -color_range pc. Następnie odtwarzam oryginalny plik dokładnie po kompresji / dekompresji. Z dokumentacji FFmpeg miałem wrażenie, że te dwa zestawy flag były równoważne, ale najwyraźniej tak nie jest. Jedynym problemem jest to, że mogę dostać ostrzeżenie z nią zestaw flag: [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly. Znalazłem również ten raport o błędzie, który może być związany z moim problemem. Nie jestem pewien „właściwego” sposobu robienia rzeczy bez użycia pozornie przestarzałego formatu pikseli yuvj420p.

Nick C.
źródło
1
Ponieważ dane są dekompresowane, lepiej byłoby, gdybyś przekształcił je oba do formatu tekstowego (np. Używając hexdump) i uruchomił na nim diff. diffpowie po prostu, że pliki są gdzieś inne. Jeden bit, jeden megabajt, wszystko jest takie samo. Sprawdzając różnicę szesnastkową, możesz lepiej oszacować, co się stało i czy jest to coś, o co należy się martwić. Sprawdź także, czy operacja nie zaokrągliła szerokości ani wysokości filmu (zdarzyło mi się to samo).
LSerni,
1
Jednym z możliwych źródeł zakłóceń może być inne mocowanie kanału Y (zgodnie z CCIR-601). Sprawdź, czy przypadkiem nie straciłeś wartości Y poniżej 16 i powyżej 240. Zobacz także video.stackexchange.com/questions/16840/…
LSerni
1
Możesz także użyć ffmpeg, aby ponownie rozłożyć swoje filmy na pojedyncze obrazy i użyć imagemagick'scompare do ich porównania.
ksenoid
1
Dobrym sposobem, aby porównać losslessness używa skrótu muxer. Pokaż pełną moc wyjściową ffmpeg -i RecordedData.avi. libx264rgb obsługuje bgr24, więc możesz uznać ten koder za opcję.
llogan
1
Po prostu koduj je bezstratnie za pomocą trybu RGB x264 (pomiń konwersję formatu pikseli).
Gyan

Odpowiedzi:

6

To nie jest prosta odpowiedź na twój rzeczywisty problem, ale rozważę użycie wewnętrznego FFV1kodeka FFmpeg :

$ ffmpeg -i raw-gray.mkv -c:v ffv1 ffv1.mkv

Alternatywnie, jego wersja 3:

$ ffmpeg -i raw-gray.mkv -c:v ffv1 -level 3 ffv1.mkv

Następnie:

$ ffmpeg -i ffv1.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
$ diff -sq raw-ffv1.yuv raw-gray.yuv
Files raw-ffv1.yuv and raw-gray.yuv are identical

Podczas używania nie jest tak wydajny jak libx264 w trybie bezstratnym yuv420p, ale jest bardziej wydajny niż używanie libx264 z bgr24(w moich testach szybkość przesyłania danych była gdzieś pomiędzy). Niektóre instytucje, takie jak Biblioteka Kongresu, uznają również FFV1 za odpowiedni format zachowania .

slhck
źródło
Jest to jednak odpowiedź na moje pierwotne podstawowe pytanie, które zredagowałem, aby wyjaśnić. Nie spotkałem żadnych problemów z FFV1. W rzeczywistości FFV1 osiągnął prawie taki sam współczynnik kompresji jak libx264 (w / -crf 0 -preset medium) dla mojego konkretnego filmu i było to szybsze. Co więcej, bezpośrednio obsługuje grayformat pikseli. Rzeczywiście wydaje się to doskonałym rozwiązaniem.
Nick C.