Tôi có một video đến từ một máy ảnh đứng yên. Cả độ phân giải và FPS đều khá cao. Dữ liệu tôi nhận được ở định dạng Bayer và sử dụng 10 bit cho mỗi pixel. Vì không có loại dữ liệu 10 bit trên nền tảng của tôi, dữ liệu gốc được lưu trữ trong bộ nhớ bằng các từ 16 bit. Tôi muốn thực hiện một số loại nén dữ liệu không mất dữ liệu trước khi truyền dữ liệu qua mạng.
- Máy ảnh không di chuyển, vì vậy các phần lớn của các khung hình liên tiếp gần như giống hệt nhau - nhưng vẫn không hoàn toàn, do tiếng ồn không thể tránh khỏi (khử nhiễu không phải là một lựa chọn, vì nó được coi là không mất mát và không nên "mất" ngay cả tiếng ồn ).
- Do FPS cao, ngay cả những phần thay đổi cũng không thay đổi nhiều giữa hai khung hình liên tiếp.
- Tuy nhiên, có vẻ như máy ảnh cũng rung lên một chút. Rất ít, nhưng vẫn còn, ngay cả các đối tượng đứng yên không hoàn toàn như vậy trong không gian hình ảnh.
- Việc nén phải được thực hiện nhanh chóng, vì vậy tôi không thể thu thập nhiều khung hình và nén tất cả chúng lại với nhau, nhưng tôi có thể nhìn lại 1 khung hình và sử dụng nó làm tài liệu tham khảo.
Dựa trên những điều trên, suy nghĩ đầu tiên của tôi là đóng gói dữ liệu, để 6 bit dự phòng đó không bị lãng phí trên mỗi từ. Tuy nhiên, tôi nghĩ rằng nếu tôi sử dụng một số mã hóa entropy (ví dụ Huffman, v.v.), thì sự dư thừa đó sẽ được tự động tính đến, do đó không cần đóng gói thêm. Vì vậy, tôi đã làm như sau:
- Lấy chênh lệch nhị phân giữa hai khung liên tiếp. Phạm vi dữ liệu ban đầu là 0 ~ 1023 (ví dụ 10 bit không dấu). Dữ liệu khác biệt được ký và phạm vi tăng lên -1023 ~ 1023, nhưng biến thể dữ liệu (hoặc thuật ngữ toán học chính xác) trở nên ít hơn nhiều so với dữ liệu gốc, trên thực tế, hầu hết các giá trị gần như không có gì đáng ngạc nhiên .
- Áp dụng gạo mã hóa cho sự khác biệt. Theo những gì tôi hiểu, có vẻ như là một lựa chọn tốt cho các tập dữ liệu có giá trị số nhỏ.
Điều này giúp tôi giảm khoảng 60% kích thước cho các khung hình 1280x720 và hệ thống thử nghiệm của tôi (Linux trong VirtualBox trên một lõi) có thể thực hiện ~ 40 lần nén như vậy mỗi giây (mà không cần tối ưu hóa nhiều). Không phải là tuyệt vời, nhưng hợp lý, tôi đoán (hoặc là nó?).
Có cách nào tốt hơn không? Bất kỳ sai lầm phổ biến tôi đã làm? Bất kỳ bước chung tôi đã bỏ lỡ? Các khung có độ phân giải cao hơn có thể được sử dụng sau này - tôi có nên mong đợi tốc độ nén tốt hơn cho kích thước khung lớn hơn không?
CẬP NHẬT:
- Tôi đã sử dụng thư viện này để mã hóa Rice. Thư viện rất chậm (bản thân tác giả mô tả nó như một thứ gì đó để học chứ không phải để sử dụng thực sự), ví dụ, nó đọc và ghi từng bit một trong các vòng lặp, giết chết hiệu suất. Ban đầu nó chỉ cho tôi ~ 20 FPS, sau khi tối ưu hóa rất cơ bản, nó trở thành 40 FPS (như đã báo cáo ở trên), sau đó tôi đã tối ưu hóa nó thêm một chút nữa, nó trở thành 80. Đó là trên một lõi i7 mà không cần vector hóa.
- Mặc dù vậy, đối với vector hóa, thật không may, tôi không thể nghĩ ra cách để vector hóa mã Rice (thậm chí không biết liệu nó có khả thi hay không - không thể tìm thấy bất kỳ dữ liệu nào về mã Rice, những gì tôi có thể tìm thấy về mã Huffman cho thấy rằng nó tuần tự và không thể được vector hóa một cách hiệu quả, có thể áp dụng cho mã Rice cũng như các mã có độ dài thay đổi khác).
- Tôi cũng đã thử một cách tiếp cận hoàn toàn khác: chia dữ liệu thành các phần nhỏ (ví dụ như apiece 64 pixel) và sử dụng triệt tiêu không đơn giản. Chúng tôi tìm thấy số lớn nhất trong một khối, ghi số bit cần thiết để thể hiện nó ở đầu khối (trong 4 trường hợp của tôi là bắt buộc), sau đó giảm tất cả các số trong khối xuống cùng một số chút ít. Tôi dự đoán tốc độ nén là xấu, nhưng nếu các mảnh nhỏ, nhiều trong số chúng sẽ không có nhiễu, do đó, chênh lệch nhị phân của chúng có thể giảm xuống còn 4 ~ 6 bit cho mỗi giá trị, và thực tế, chỉ có vậy kém hơn khoảng 5% so với mã Rice, trong khi nhanh gấp khoảng hai lần (ví dụ 160 FPS cho trường hợp của tôi). Tôi đã thử vector hóa nó, nhưng tôi hơi bị vectơ hóa, vì vậy có lẽ vì điều đó tôi chỉ có thể đạt được khoảng x1,8 tốc độ tăng tốc hơn nữa.
Vì các số âm không có số 0 đứng đầu, tôi đã áp dụng mã hóa zigzag sau chênh lệch nhị phân và trước khi triệt tiêu Rice / zero.