Giới thiệu
Trong thế giới công nghệ, "mãi mãi" có nghĩa là khoảng 5 năm. Thật khiêm tốn khi nghĩ rằng tiêu chuẩn hình ảnh JPEG năm 1992 vẫn còn mạnh mẽ mặc dù đã hơn 5 "mãi mãi". Tại sao nó lại thành công như vậy? Bài viết này trình bày những ý tưởng chính đằng sau JPEG bằng ngôn ngữ dễ hiểu và bao gồm một trình nén JPEG tương tác ngay trên trang để bạn có thể chơi ở nhà.
Phương pháp nén
Các kỹ thuật nén tìm kiếm các mẫu lặp lại trong dữ liệu và sau đó thay thế các mẫu đó bằng các mẫu ngắn hơn. Giống như sử dụng một từ viết tắt hoặc từ viết tắt để thay thế cho một từ hoặc cụm từ dài hơn. Video, hình ảnh tĩnh và âm thanh thường không nén tốt. Vấn đề với hình ảnh và âm thanh là dữ liệu này thường quá nhiễu để tìm ra các từ viết tắt phù hợp. Vì lý do này, JPEG và nhiều định dạng phương tiện khác sử dụng thứ gọi là nén mất dữ liệu.
Nén mất dữ liệu có nghĩa là bạn giảm kích thước tệp bằng cách loại bỏ một số thông tin. Giả sử một thủ thư đã hết chỗ trên kệ và cần chỗ cho nhiều sách hơn. Nếu cô ấy thay thế một số sách bằng bản sao kỹ thuật số hoặc vi phim, thì đó là nén không mất dữ liệu. Nếu cô ấy đốt một số cuốn sách, đó chính là sự nén mất dữ liệu.
Bí quyết để nén mất dữ liệu tốt là loại bỏ thông tin mà không ai quan tâm: đốt những cuốn sách mà không ai từng đọc. Làm thế nào để quyết định giữ lại những gì? Khoa học! Trong trường hợp nén hình ảnh, bạn bắt đầu bằng cách hiểu những phần nào của hình ảnh là quan trọng đối với nhận thức của con người và những phần nào không. Sau đó, bạn tìm cách giữ lại những phẩm chất quan trọng và loại bỏ phần còn lại. Trong JPEG, nén mất dữ liệu dựa trên hai nguyên tắc tâm lý thị giác:
1. Thay đổi về độ sáng quan trọng hơn thay đổi về màu sắc: võng mạc của con người chứa khoảng 120 triệu tế bào que nhạy cảm với độ sáng, nhưng chỉ có khoảng 6 triệu tế bào nón nhạy cảm với màu sắc.
2. Thay đổi tần số thấp quan trọng hơn thay đổi tần số cao. Mắt người giỏi đánh giá những thay đổi về ánh sáng tần số thấp, như các cạnh của vật thể. Nó kém chính xác hơn trong việc đánh giá những thay đổi về ánh sáng tần số cao, như các chi tiết nhỏ trong một họa tiết hoặc kết cấu bận rộn. Ngụy trang có hiệu quả một phần vì các họa tiết tần số cao hơn làm gián đoạn các cạnh tần số thấp hơn của vật được ngụy trang.
Một con báo đi bộ với lớp ngụy trang một phần gần một chiếc xe ở Nam Phi. Ảnh: Lee R. Berger.
Nén JPEG áp dụng từng ý tưởng này theo lượt. Trong mỗi trường hợp, dữ liệu hình ảnh được chuyển đổi để dễ dàng truy cập vào loại thông tin cần thiết (thông tin về độ sáng hoặc tần số). Sau đó, một số thông tin ít quan trọng hơn sẽ bị loại bỏ. Bước cuối cùng, thông tin còn lại được nén bằng phương pháp nén không mất dữ liệu truyền thống để đóng gói kết quả cuối cùng vào không gian nhỏ nhất có thể. Trong bài viết này, chúng ta sẽ khám phá quy trình từng bước, sử dụng hình ảnh thực và theo dõi chúng trong toàn bộ quá trình mã hóa (lưu dưới dạng JPEG) và giải mã (tải từ JPEG). Bạn có thể thử nghiệm các cài đặt mã hóa và xem nó ảnh hưởng đến kết quả như thế nào.
Bắt đầu thôi!
PHẦN I .MÃ HÓA
Bắt đầu bằng cách chọn hình ảnh đầu vào để nén.
Hình ảnh đầu vào:
Chọn một hình ảnh từ danh sách được cung cấp. Có một số hình ảnh để thử nghiệm, nhưng tôi khuyên bạn nên sử dụng hình ảnh "Tower" mặc định cho lần đầu tiên. Hình ảnh này có sự kết hợp tốt giữa các phân đoạn tần số thấp và cao, và đôi khi tôi sẽ đề cập đến hình ảnh này trong văn bản bài viết.
STT | ẢNH MINH HỌA |
1 | |
2 | |
3 | |
4 | |
5 |
Bạn cũng có thể sử dụng hình ảnh theo ý muốn bằng cách chọn Chọn hình ảnh của riêng bạn.
Bước 1: Tách thông tin màu sắc
| Hình ảnh máy tính thông thường được tạo thành từ một lưới các ô vuông nhỏ màu gọi là pixel. Mỗi pixel được lưu trữ dưới dạng ba số, biểu thị lượng ánh sáng đỏ, xanh lá cây và xanh lam cần thiết để tái tạo màu của pixel đó. Vì lý do này, nó được gọi là hình ảnh RGB. Ở phía bên trái của hình minh họa bên trái, bạn có thể thấy các phần màu đỏ, xanh lá cây và xanh lam của hình ảnh đã chọn của bạn được chia thành ba kênh riêng biệt. |
Một hình ảnh được tạo thành từ các điểm ảnh. Màu sắc của mỗi điểm ảnh là tổng lượng ánh sáng đỏ, xanh lá cây và xanh lam.
Vấn đề, xét về JPEG, là thông tin độ sáng của hình ảnh được phân bổ đều qua các kênh R, G và B. Hãy nhớ rằng độ sáng quan trọng hơn màu sắc, vì vậy chúng ta sẽ muốn tách độ sáng khỏi thông tin màu sắc để có thể xử lý riêng. Để thực hiện điều này, JPEG sử dụng một số phép toán để chuyển đổi không gian màu của hình ảnh từ RGB sang YCbCr. Một hình ảnh YCbCr cũng có ba kênh, nhưng nó lưu trữ tất cả thông tin độ sáng trong một kênh (Y) trong khi chia thông tin màu giữa hai kênh còn lại (Cb và Cr).
Phía bên phải của hình minh họa bên trái cho thấy cùng một hình ảnh được chia thành các kênh Y (trên cùng), Cb (giữa) và Cr (dưới cùng). Lưu ý rằng các kênh Cb và Cr "bẩn" vì tất cả các định nghĩa do thông tin độ sáng cung cấp đã được chuyển sang kênh Y.
Để giữ kích thước của hình minh họa hợp lý, tôi đã thu nhỏ tất cả các kênh. Trên thực tế, mỗi kênh có cùng kích thước với hình ảnh gốc.
Bước 2: Bỏ đi một số thông tin về màu sắc
|
Trước khi thực hiện bất kỳ thao tác nào khác, JPEG sẽ loại bỏ một số thông tin màu bằng cách thu nhỏ kênh Cb và Cr (màu) trong khi vẫn giữ nguyên kênh Y (độ sáng) quan trọng ở kích thước đầy đủ. Nói một cách chính xác, bước này là tùy chọn. Tiêu chuẩn cho biết bạn có thể giữ lại toàn bộ thông tin màu, một nửa hoặc một phần tư. Đối với hình ảnh, hầu hết các ứng dụng sẽ giữ lại một nửa thông tin màu; đối với video, thường là một phần tư. Đối với bản demo này, tôi giữ lại một phần tư, vừa để phóng đại hiệu ứng vừa để minh họa đẹp hơn. |
Lưu ý rằng, chúng ta bắt đầu với 3 kênh đầy đủ và bây giờ chúng ta có 1 kênh đầy đủ và 2 kênh × ¼, tổng cộng là 1½. Chúng ta chỉ mới bắt đầu và chúng ta đã giảm xuống còn một nửa thông tin mà chúng ta đã bắt đầu!
Bước 3: Chuyển đổi sang miền tần số
| Để sử dụng quan sát thứ hai về nhận thức thị giác của con người, chúng ta bắt đầu bằng cách chia mỗi kênh Y, Cb và Cr thành các khối pixel 8×8. Chúng ta sẽ chuyển đổi từng khối này từ miền không gian sang miền tần số. |
Hãy xem xét một trong những khối 8×8 này từ kênh Y. Miền không gian là những gì chúng ta có bây giờ: giá trị ở góc trên bên trái biểu thị độ sáng (giá trị Y) của điểm ảnh ở góc trên bên trái của khối đó. Tương tự như vậy, giá trị ở góc dưới bên phải biểu thị độ sáng của điểm ảnh ở góc dưới bên phải của khối đó. Do đó, thuật ngữ không gian: vị trí trong khối biểu thị vị trí trong hình ảnh. Khi chúng ta chuyển đổi khối này sang miền tần số, vị trí trong khối thay vào đó sẽ biểu thị một dải tần số trong khối đó của hình ảnh. Giá trị ở góc trên bên trái của khối sẽ biểu thị thông tin tần số thấp nhất và giá trị ở góc dưới bên phải của khối sẽ biểu thị thông tin tần số cao nhất.
Phép biến đổi miền này được thực hiện bằng một chút thủ thuật toán học gọi là Biến đổi Cosin rời rạc 2D (DCT). (Nếu bạn đã nghe về biến đổi Fourier, DCT cũng tương tự nhưng chỉ sử dụng số thực; điều này thuận tiện hơn cho việc biểu diễn trên máy tính.) Ý tưởng cốt lõi là biểu diễn các giá trị trong khối 8×8 dưới dạng tổng các hàm cosin, trong đó mỗi hàm cosin có một tần số duy nhất cụ thể.
Bạn không cần hiểu toán học để hiểu cách thức hoạt động của nó. Hãy xem hình minh họa tần số Y cho hình ảnh Tháp. Bạn có thể thấy rõ góc trên bên trái của mỗi khối 8×8 nhờ một chấm tối thông tin tần số thấp. Bây giờ, nếu bạn nhìn vào các khối từ các phần bầu trời của hình ảnh, bạn sẽ thấy phần còn lại của mỗi khối hầu như trống rỗng. Bầu trời không có nhiều thay đổi đáng kể từ pixel này sang pixel khác: không có thông tin tần số cao. So sánh điều đó với các khối từ các phần tháp của hình ảnh: kết cấu bận rộn của các viên gạch có nghĩa là có nhiều thay đổi tần số cao hơn và điều này hiển thị dưới dạng màu xám trên toàn bộ khối.
Bước 4: Thanh trượt chất lượng (lượng tử hóa)
Bước tiếp theo là loại bỏ một số thông tin tần số một cách có chọn lọc. Nếu bạn đã từng lưu một hình ảnh JPEG và chọn một giá trị chất lượng, thì đây chính là lúc lựa chọn đó phát huy tác dụng. Nó hoạt động như sau: bắt đầu với hai bảng số nguyên 8×8, được gọi là bảng lượng tử hóa. Một bảng dành cho thông tin độ sáng và một bảng dành cho thông tin màu. Bạn sẽ sử dụng những con số này trên mỗi khối 8×8 trong dữ liệu hình ảnh bằng cách chia giá trị tần số trong dữ liệu hình ảnh cho số tương ứng trong bảng lượng tử hóa của nó. Vì vậy, góc trên cùng bên trái của mỗi khối 8×8 trong kênh tần số Y sẽ được chia cho số ở góc trên cùng bên trái của bảng lượng tử hóa độ sáng, v.v. Kết quả của mỗi phép chia được làm tròn đến số nguyên gần nhất và các phần thập phân bị loại bỏ.
|
|
Hiệu ứng của lựa chọn của bạn đối với hình ảnh đầu ra cuối cùng được hiển thị để tham khảo.
Một số càng lớn trong một trong các bảng lượng tử hóa, thì càng có nhiều thông tin bị loại bỏ khỏi phần đó của dải tần số đó. Vì chúng ta ít quan tâm đến thông tin tần số cao, nên các số trong khu vực đó của các bảng lượng tử hóa sẽ lớn hơn. Và vì chúng ta ít quan tâm đến màu sắc hơn là độ sáng, nên các số trong bảng màu sẽ lớn hơn tổng thể so với các số trong bảng độ sáng.
Các bảng lượng tử hóa được lưu cùng với dữ liệu hình ảnh trong tệp JPEG. Chúng sẽ cần thiết để giải mã hình ảnh chính xác. Tiếp tục và chơi với thanh trượt chất lượng ở trên. Lưu ý rằng thông tin tần số ngày càng biến mất khi bạn kéo chất lượng xuống mức thấp.
Bước 5: Nén dữ liệu không mất dữ liệu
Nếu bạn suy nghĩ cẩn thận về những gì vừa xảy ra, bạn sẽ nhận ra rằng mặc dù chúng ta đã loại bỏ một số thông tin tần số bằng cách loại bỏ các phần thập phân sau khi chia, chúng ta vẫn có cùng một lượng dữ liệu: một số cho mỗi pixel từ mỗi kênh trong ba kênh. Có vẻ như bước đó thực sự không mang lại cho chúng ta bất cứ thứ gì. Tuy nhiên, dữ liệu này hiện sẽ được nén bằng cách sử dụng nén không mất dữ liệu truyền thống. Nhưng hãy đợi đã, lý do duy nhất khiến chúng ta sử dụng nén có mất dữ liệu ngay từ đầu không phải là nén không mất dữ liệu không hiệu quả đối với hình ảnh sao? Đúng vậy, nhưng quá trình lượng tử hóa mà chúng ta vừa thực hiện sẽ làm cho dữ liệu có thể nén được nhiều hơn bằng cách làm cho dữ liệu ít nhiễu hơn. Để biết lý do, hãy so sánh ba chuỗi số sau:
Hàng đầu tiên liệt kê các giá trị cho, ví dụ, một số pixel trong kênh tần số Y. Hàng thứ hai là các giá trị tương tự chia cho 2 và làm tròn; hàng thứ ba chia cho 16 và làm tròn. Bạn có thể thấy rằng số chia càng lớn thì dữ liệu sẽ càng có nhiều sự lặp lại. Và dữ liệu càng có nhiều sự lặp lại thì việc nén càng dễ dàng và tệp hình ảnh cuối cùng sẽ càng nhỏ.
JPEG có một mẹo cuối cùng để làm cho dữ liệu dễ nén hơn: nó liệt kê các giá trị cho mỗi khối 8x8 theo mẫu zíc zắc sắp xếp các số theo thứ tự từ tần số thấp nhất đến cao nhất. Điều đó có nghĩa là các phần được lượng tử hóa nhiều nhất (với các ước số lớn nhất) nằm cạnh nhau để tạo ra các mẫu lặp lại đẹp mắt của các số nhỏ.
Dữ liệu khối được nén theo thứ tự ngoằn ngoèo, nhóm các tần số tương tự lại với nhau.
PHẦN II.GIẢI MÃ
Đó là những yếu tố thiết yếu để viết một hình ảnh JPEG: chuyển đổi hình ảnh từ RGB sang YCbCr để chúng ta cô lập độ sáng, loại bỏ một số màu sắc, chuyển đổi sang miền tần số, loại bỏ một số độ chính xác của thông tin tần số và nén dữ liệu kết quả.
Điều gì xảy ra khi bạn đọc lại hình ảnh? Về cơ bản, bạn chỉ cần đảo ngược từng bước của quá trình mã hóa. Chúng ta hãy cùng tìm hiểu từng bước.
Bước 6: Giải nén
|
Bước đầu tiên là giải nén dữ liệu tần số được lượng tử hóa (chia và làm tròn). Vì dữ liệu này được nén không mất dữ liệu, nên kết quả sẽ giống hệt như trong Bước 5 ở trên. |
Bước 7: Tái tạo từ dữ liệu lượng tử
|
Tiếp theo, chúng ta cần đảo ngược quá trình lượng tử hóa. Chúng ta sử dụng cùng một quy trình như trước, nhưng thay vì chia cho các số trong bảng, chúng ta nhân. Vì chúng ta làm tròn các số, chúng ta sẽ không nhận được chính xác cùng một số. Kết quả là một phép tính xấp xỉ không hoàn hảo của dữ liệu tần số ban đầu, bị giới hạn ở độ chính xác được cho phép bởi các bảng lượng tử hóa. Chất lượng càng thấp, các ước lượng lượng tử hóa càng lớn, độ chính xác càng bị mất và quá trình tái tạo của chúng ta sẽ càng kém chính xác. |
Bước 8: Chuyển đổi trở lại miền không gian
| Bây giờ chúng ta đã tái tạo thông tin tần số, chúng ta cần chuyển đổi nó trở lại từ miền tần số sang miền không gian. Điều này không thành vấn đề. Phép biến đổi mà chúng ta sử dụng trong quá trình mã hóa có một phép nghịch đảo thực hiện công việc đó.
Bây giờ dữ liệu đã ở dạng dễ nhận biết hơn, chúng ta có thể bắt đầu đánh giá mức độ dễ nhận biết của việc mất thông tin. |
Bước 9: Điền thông tin màu còn thiếu
Cb
Cr
| Để kết hợp các kênh trở lại thành một hình ảnh duy nhất, chúng ta cần thu nhỏ hai kênh màu Cb và Cr trở lại kích thước ban đầu của chúng. Nhưng thông tin chúng ta đã vứt đi đã biến mất, vì vậy chúng ta sẽ phải ước tính nó bằng nội suy. Chúng ta sẽ điền vào các pixel bị thiếu bằng cách lấy giá trị trung bình của các pixel xung quanh vẫn còn đó. Có nhiều cách khác nhau để thực hiện việc này và không có cách nào là hoàn hảo. Hình ảnh được thu nhỏ sẽ có xu hướng bị khối hoặc mờ, tùy thuộc vào phương pháp được sử dụng. |
Đồ họa sóc chuột được phóng to lên 400% bằng hai phương pháp khác nhau. Một hình ảnh được phóng to là hình khối, hình ảnh còn lại là hình mờ.
Bước 10: Chuyển đổi trở lại RGB
|
Lúc này chúng ta đã có một hình ảnh hoàn chỉnh, nhưng nó vẫn ở không gian màu YCbCr, mà máy tính không thể hiển thị trực tiếp. Chúng ta cần chuyển đổi nó trở lại không gian màu RGB mà chúng ta đã bắt đầu. |
Hình ảnh đầu ra:
Input
Output
Sự khác biệt
| Cuối cùng, chúng ta có thể kết hợp các kênh R, G và B riêng biệt trở lại thành một hình ảnh duy nhất và hiển thị kết quả. Để so sánh, cả hình ảnh đầu vào gốc và hình ảnh đầu ra đã giải mã đều được hiển thị ở bên trái. Bên dưới là "hình ảnh khác biệt" làm nổi bật sự khác biệt giữa hai hình ảnh: các điểm ảnh tối hơn có nghĩa là đầu ra khác biệt nhiều hơn so với đầu vào tại vị trí đó.
Bạn đã có nó rồi. Chúng tôi đã lấy một hình ảnh đầu vào, mã hóa nó, giải mã nó và nhận được một hình ảnh tương tự trở lại. Đó là JPEG. Bây giờ bạn đã thấy toàn bộ quá trình, hãy quay lại và thử nghiệm với một số hình ảnh khác. |
TÌM HIỂU VÀ TẢI THÊM TÀI LIỆU TẠI ĐÂY:
1.
2.
3.