ビデオストリームの高速でロスレスな圧縮
静止カメラからのビデオがあります。解像度とFPSはどちらも非常に高いです。私が取得するデータはバイエル形式で、ピクセルあたり10ビットを使用します。プラットフォームには10ビットデータ型がないため、元のデータは16ビットワードを使用してメモリに保存されます。ネットワークを介してデータを送信する前に、何らかの種類のデータのロスレス圧縮を実装したいと思います。 カメラは動かないので、連続するフレームの大部分はほぼ同一ですが、避けられないノイズのために完全ではありません(ノイズがなくてもノイズを「失う」べきではないため、ノイズ除去はオプションではありません)。 FPSが高いため、変化する部分でさえ、2つの連続するフレーム間であまり変化しません。 ただし、カメラも少し揺れているようです。非常にわずかですが、それでも、静止したオブジェクトでさえ、画像空間では完全にはそうではありません。 圧縮はオンザフライで実行する必要があるため、多くのフレームを収集してそれらをまとめて圧縮することはできませんが、1フレーム後ろを見て参照として使用できます。 上記に基づいて、私が最初に考えたのは、データをビットパックすることで、これらの6つの冗長ビットがすべての単語で無駄にならないようにしました。ただし、エントロピーコーディング(ハフマンなど)を使用すると、その冗長性が自動的に考慮されるため、追加のパッキングは必要ないと考えました。だから私は次のことをしました: 2つの連続するフレーム間でバイナリの差分を取りました。元のデータ範囲は0〜1023(たとえば、符号なし10ビット)でした。差分データは符号付きになり、範囲は-1023〜1023に増加しますが、データの変動(または正しい数学用語)は元のデータよりもはるかに小さくなります。実際、ほとんどの値は驚くことではありませんが、ゼロに近いです。 。 違いにライスコーディングを適用しました。私が理解していることから、ほとんど数値が小さいデータセットには良い選択のように見えます。 これにより、1280x720フレームのサイズが約60%削減され、テストシステム(シングルコアのVirtualBoxのLinux)は、1秒あたり約40の圧縮を(最適化なしで)実行できます。それほど素晴らしいわけではありませんが、合理的だと思います(またはそうでしょうか?)。 より良い方法はありますか?よくある間違いはありますか?逃した一般的な手順はありますか?高解像度のフレームは後で使用される可能性があります-フレームサイズが大きいほど、圧縮率が向上すると思いますか? UPD .: このライブラリをライスエンコーディングに使用しました。ライブラリは非常に低速です(著者自身が実際の使用ではなく学習用と記述しています)。たとえば、ループでビットを1つずつ読み書きするため、パフォーマンスが低下します。最初は〜20 FPSしか与えられませんでしたが、いくつかの非常に基本的な最適化の後、40 FPS(上記のように)になり、後でさらに最適化して80になりました。 しかし、ベクトル化に関しては、残念ながら、Riceコードをベクトル化する方法を考えることができませんでした(それが可能かどうかさえわからない-Riceコードに関するデータを見つけることができませんでした、ハフマンコードについて見つけることができることはこれはシーケンシャルであり、効率的にベクトル化することはできません。これは、ライスコードや他の可変長コードに適用される可能性があります。 また、まったく異なるアプローチを試みました。データを小さな断片に分割し(例:64ピクセルごとに)、単純なゼロ抑制を使用します。ブロック内で最大の数を見つけ、それを表すために必要なビット数をブロックの先頭に書き込みます(私の場合、追加の4ビットが必要でした)。次に、ブロック内のすべての数を同じ数に減らします。ビット。私は圧縮率が悪いと思っていましたが、断片が小さい場合、それらの多くはノイズスパイクを持たないため、バイナリ差は値ごとに4〜6ビットのようなものに減らすことができ、実際にはそれだけでしたRiceコードよりも約5%悪いですが、約2倍高速です(たとえば、私の場合は160 FPS)。私はそれをベクトル化しようとしましたが、ベクトル化をちょっと嫌っています。 負数には先行ゼロがないため、バイナリ差分の後、ライス/ゼロ抑制の前にジグザグエンコーディングを適用しました。