Saya punya video yang berasal dari kamera stasioner. Baik resolusi dan FPS cukup tinggi. Data yang saya dapatkan adalah dalam format Bayer dan menggunakan 10 bit per piksel. Karena tidak ada tipe data 10 bit di platform saya, data asli disimpan dalam memori menggunakan kata-kata 16-bit. Saya ingin menerapkan semacam kompresi data tanpa kehilangan sebelum mentransmisikannya melalui jaringan.
- Kamera tidak bergerak, jadi bagian besar dari frame yang berurutan hampir identik - tetapi masih belum sepenuhnya, karena noise yang tidak terhindarkan (denoising bukan pilihan, karena seharusnya lossless dan tidak boleh "kehilangan" bahkan noise) ).
- Karena FPS tinggi, bahkan bagian yang berubah tidak banyak berubah di antara dua frame yang berurutan.
- Namun, sepertinya kamera juga bergetar sedikit. Sangat sedikit, tapi tetap saja, bahkan benda-benda yang diam tidak sepenuhnya berada di ruang gambar.
- Kompresi harus dilakukan dengan cepat, jadi saya tidak bisa mengumpulkan banyak frame dan mengompres semuanya, tapi saya bisa melihat 1 frame kembali dan menggunakannya sebagai referensi.
Berdasarkan hal di atas, pikiran pertama saya adalah meng-bit-data, sehingga 6 bit redundan itu tidak terbuang sia-sia untuk setiap kata. Namun, saya berpikir bahwa jika saya menggunakan beberapa pengkodean entropi (misalnya Huffman dll.), Redundansi itu akan secara otomatis diperhitungkan, jadi tidak perlu pengepakan tambahan. Jadi saya sudah melakukan yang berikut:
- Mengambil perbedaan biner antara dua frame berturut-turut. Rentang data asli adalah 0 ~ 1023 (mis. 10 bit yang tidak ditandatangani). Perbedaan data menjadi masuk dan kisarannya meningkat menjadi -1023 ~ 1023, tetapi variasi data (atau apa istilah matematika yang benar) menjadi jauh lebih sedikit daripada dalam data asli, pada kenyataannya, sebagian besar nilai, tidak mengherankan, mendekati nol .
- Pengodean Beras Terapan untuk perbedaan. Dari apa yang saya mengerti, sepertinya pilihan yang baik untuk set data nilai numerik sebagian besar kecil.
Ini memberi saya pengurangan sekitar 60% dalam ukuran untuk 1280x720 frame, dan sistem pengujian saya (Linux dalam VirtualBox pada satu inti) dapat melakukan ~ 40 kompresi seperti itu per detik (tanpa banyak optimasi). Tidak terlalu bagus, tapi masuk akal, kurasa (atau itu?).
Apakah ada cara yang lebih baik? Adakah kesalahan umum yang saya buat? Adakah langkah umum yang saya lewatkan? Bingkai resolusi yang lebih tinggi dapat digunakan nanti - haruskah saya mengharapkan tingkat kompresi yang lebih baik untuk ukuran bingkai yang lebih besar?
UPD .:
- Saya menggunakan perpustakaan ini untuk pengkodean Rice. Perpustakaan sangat lambat (penulis sendiri menggambarkannya sebagai sesuatu untuk belajar daripada untuk penggunaan nyata), misalnya membaca dan menulis bit satu per satu dalam loop, yang membunuh kinerja. Awalnya hanya memberi saya ~ 20 FPS, setelah beberapa optimasi yang sangat dasar menjadi 40 FPS (seperti yang dilaporkan di atas), kemudian saya optimalkan lagi, menjadi 80. Itu adalah pada inti i7 tunggal tanpa vektorisasi.
- Sedangkan untuk vektorisasi, sayangnya, saya tidak bisa memikirkan cara untuk membuat vektor kode Beras (bahkan tidak tahu apakah itu mungkin - tidak dapat menemukan data pada kode Beras, apa yang dapat saya temukan tentang kode Huffman menunjukkan bahwa ini berurutan dan tidak dapat secara efisien di-vektor, yang mungkin berlaku untuk kode Beras serta kode panjang variabel lainnya).
- Saya juga mencoba pendekatan yang sama sekali berbeda: memecah data menjadi potongan-potongan kecil (misalnya, masing-masing 64 pixel) dan menggunakan penekanan nol sederhana. Kami menemukan angka terbesar dalam sebuah blok, menulis jumlah bit yang diperlukan untuk mewakilinya ke awal blok (4 bit tambahan diperlukan untuk itu, dalam kasus saya), kemudian mengurangi semua angka dalam blok ke jumlah yang sama bit. Saya perkirakan tingkat kompresi menjadi buruk, tetapi jika kepingannya kecil, banyak dari mereka tidak akan memiliki lonjakan noise, oleh karena itu perbedaan binernya dapat dikurangi menjadi sekitar 4 ~ 6 bit per nilai, dan itu, pada kenyataannya, hanya sekitar 5% lebih buruk daripada kode Beras, sementara menjadi sekitar dua kali lebih cepat (misalnya 160 FPS untuk kasus saya). Saya mencoba melakukan vektorisasi, tetapi saya agak menyedot vektorisasi, jadi mungkin karena itu saya hanya dapat mencapai sekitar x1.8 percepatan lebih lanjut.
Karena bilangan negatif tidak memiliki nol di depan, saya menerapkan pengkodean zigzag setelah perbedaan biner dan sebelum penekan Rice / nol.
sumber
Jawaban:
Anda punya prediksi temporal, tetapi tidak ada spasial. Untuk kompresi yang lebih baik dengan biaya kecepatan, Anda harus dapat menggunakan piksel di atas dan di sebelah kiri piksel saat ini di bingkai saat ini sebagai prediktor, serta piksel di lokasi yang sama di bingkai sebelumnya. Alasan untuk hanya melihat ke atas dan ke kiri adalah sama dengan alasan untuk hanya melihat pada bingkai sebelumnya; Anda hanya ingin bergantung pada data yang sudah Anda dekodekan, dan batasi berapa banyak yang harus Anda simpan.
Kode Rice mungkin merupakan tradeoff yang baik antara efisiensi dan kecepatan, tetapi kode Huffman statis (yang diperhitungkan oleh Anda pada sampel data video) mungkin lebih efisien dan sama cepatnya.
Sedangkan untuk kecepatan, pastikan kode Anda mendapatkan vektor - baik dengan menggunakan flag compiler yang tepat dan pola kode untuk memungkinkan kompiler untuk auto-vectorize, atau dengan menulis tangan kode untuk menggunakan intrinsik vektor atau perakitan.
Akhirnya, apakah turun menjadi 8 bit per piksel kemungkinan? Jelas itu meninggalkan ranah "lossless", tetapi tidak hanya akan mengurangi ukuran output terkompresi Anda, itu juga, dengan kode vektor, mungkin meningkatkan throughput Anda hingga 2x.
sumber
x5
dengan perbedaan(x5 - x4)
?Anda mungkin paling baik dilayani dengan menggunakan implementasi kompresi dan dekompresi yang ada. Implementasi Anda saat ini tampaknya mirip dengan codec HuffYUV , jadi mungkin ada baiknya mencoba itu untuk melihat apakah itu bekerja cukup baik untuk Anda.
sumber