JPEG 格式的工作原理

JPEG 影像在我們的數位生活中無所不在,但在這種意識的表象背後是刪除人眼無法感知的細節的演算法。結果是以最小的檔案大小獲得最高的視覺品質 - 但這一切到底是如何運作的呢?讓我們看看我們的眼睛看不到的到底是什麼!

JPEG 格式的工作原理

人們很容易認為向朋友發送照片的能力是理所當然的,而不用擔心他們使用的設備、瀏覽器或作業系統 - 但情況並非總是如此。到 1980 世紀 XNUMX 年代初,電腦可以儲存和顯示數位影像,但對於實現這一目標的最佳方法存在許多相互競爭的想法。您不能只是將圖像從一台計算機發送到另一台計算機並希望它能起作用。

為了解決這個問題,1986年成立了一個由世界各地的專家組成的委員會,名為“攝影專家聯合組»(聯合影像專家小組,JPEG)是國際標準化組織 (ISO) 和國際電工委員會 (IEC) 這兩個總部位於瑞士日內瓦的國際標準組織共同努力成立的。

一群名為 JPEG 的人於 1992 年創建了 JPEG 數位影像壓縮標準。任何使用過 Internet 的人都可能遇到過 JPEG 編碼的影像。這是編碼、發送和儲存影像最常見的方式。從網頁到電子郵件再到社交媒體,JPEG 每天被使用數十億次——幾乎每次我們在線上查看或發送圖像時。如果沒有 JPEG,網路的色彩會更少、速度會更慢,而且貓咪的圖片可能會更少!

本文介紹如何解碼 JPEG 影像。換句話說,需要將電腦上儲存的壓縮資料轉換為螢幕上顯示的影像。這是值得了解的,不僅因為它對於理解我們每天使用的技術很重要,而且因為透過解鎖壓縮級別,我們可以更多地了解感知和視覺,以及我們的眼睛對哪些細節最敏感。

另外,這樣玩弄影像也是非常有趣的。

JPEG 格式的工作原理

探索 JPEG 內部

在計算機上,所有內容都儲存為二進制數序列。通常,這些位元(零和一)以八個為一組組成位元組。當您在電腦上開啟 JPEG 影像時,某些東西(瀏覽器、作業系統或其他東西)必須對位元組進行解碼,將原始影像還原為可顯示的顏色清單。

如果你下載了這個甜蜜的 一隻貓的照片 用文字編輯器打開它,你會看到一堆不連貫的字元。

JPEG 格式的工作原理
在這裡,我使用 Notepad++ 檢查文件的內容,因為 Windows 上的常規文字編輯器(如 Notepad)會在儲存後損壞二進位文件,並且不再滿足 JPEG 格式。

在文字處理程式中開啟影像會使電腦感到困惑,就像當您揉眼睛並開始看到顏色斑點時會混淆您的大腦一樣!

您看到的這些點被稱為 光幻視,並且不是光刺激或心靈產生幻覺的結果。它們的發生是因為您的大腦認為視神經中的任何電信號都會傳達有關光的訊息。大腦需要做出這些假設,因為無法知道訊號是聲音、視覺還是其他東西。體內的所有神經都傳送完全相同的電脈衝。透過對眼睛施加壓力,您會發送非視覺信號,但會激活眼睛的受體,您的大腦將其解釋為視覺信號(在這種情況下是錯誤的)。壓力真的是看得見摸得著!

想想電腦與大腦有多相似,這很有趣,但它也是一個有用的類比,可以說明資料的含義(無論是透過神經傳遞到身體還是儲存在電腦上)在多大程度上取決於其解釋。所有二進位資料均由 0 和 1 組成,這是可以傳達任何類型資訊的基本組成部分。您的電腦通常會使用檔案副檔名等線索來找出如何解釋它們。現在我們強制它將它們解釋為文本,因為這是文本編輯器所期望的。

要了解如何解碼 JPEG,我們需要查看原始訊號本身 - 二進位資料。這可以使用十六進位編輯器來完成,或直接在 原文文章網頁!有一個圖像,旁邊的文字欄位中是其所有位元組(標題除外),以十進位形式呈現。您可以更改它們,腳本將重新編碼並即時生成新圖像。

JPEG 格式的工作原理

透過使用這個編輯器,您可以學到很多東西。例如,您能說出像素以什麼順序儲存嗎?

這個例子的奇怪之處在於,改變一些數字根本不會影響影像,但是,例如,如果你在第一行將數字 17 替換為 0,那麼照片將完全毀掉!

JPEG 格式的工作原理

其他變更(例如將 7 行上的 1988 替換為數字 254)會變更顏色,但僅變更後續像素的顏色。

JPEG 格式的工作原理

也許最奇怪的是,有些數字不僅改變顏色,還改變影像的形狀。將第 70 行中的 12 更改為 2,然後查看圖像的頂行以了解我的意思。

JPEG 格式的工作原理

而且無論您使用什麼 JPEG 影像,在編輯位元組時您總是會發現這些神秘的西洋棋圖案。

使用編輯器時,很難理解如何從這些位元組重新建立照片,因為 JPEG 壓縮由三種不同的技術組成,並按等級順序套用。我們將分別研究每一個,以揭示我們所看到的神秘行為。

JPEG 壓縮的三個等級:

  1. 顏色子取樣.
  2. 離散餘弦變換與取樣.
  3. 行程編碼, 三角洲 и 霍夫曼

為了讓您了解壓縮的程度,請注意上圖代表 79 個數字,約 819 KB。如果我們在不壓縮的情況下儲存它,每個像素將需要三個數字 - 分別代表紅色、綠色和藍色分量。這將達到 79 個數字,或大約。 917 KB。經過JPEG壓縮後,最終檔案縮小了700倍以上!

事實上,該影像還可以壓縮得更多。下面是並排的兩張圖片 - 右邊的照片已被壓縮至 16 KB,即比未壓縮版本小 57 倍!

JPEG 格式的工作原理

如果你仔細觀察,你會發現這些圖像並不相同。兩張都是JPEG壓縮的圖像,但右邊一張的體積要小得多。它看起來也有點糟糕(看看背景顏色方塊)。這就是 JPEG 也稱為有損壓縮的原因。在壓縮過程中,影像會發生變化並失去一些細節。

1. 顏色子採樣

這是僅應用第一級壓縮的圖像。

JPEG 格式的工作原理
(互動版 - 在 原來的 文章)。刪除一個數字就會破壞所有顏色。然而,如果恰好刪除六個數字,則對影像幾乎沒有影響。

現在這些數字更容易解讀了。這幾乎是一個簡單的顏色列表,其中每個位元組恰好改變一個像素,但同時它已經是未壓縮圖像大小的一半(在這種減小的大小下將佔用大約 300 KB)。你能猜出為什麼嗎?

您可以看到這些數字並不代表標準的紅色、綠色和藍色分量,因為如果我們用零替換所有數字,我們將得到綠色影像(而不是白色)。

JPEG 格式的工作原理

這是因為這些位元組代表Y(亮度),

JPEG 格式的工作原理

Cb(相對藍度),

JPEG 格式的工作原理

和 Cr(相對紅度)圖。

JPEG 格式的工作原理

為什麼不使用RGB?畢竟,這就是大多數現代螢幕的工作方式。您的顯示器可以顯示任何顏色,包括紅色、綠色和藍色,每個像素具有不同的強度。通過以全亮度打開所有三個來獲得白色,通過關閉它們來獲得黑色。

JPEG 格式的工作原理

這也與人眼的工作方式非常相似。我們眼睛裡的顏色感受器被稱為“視錐細胞”,並分為三種類型,每種類型對紅色、綠色或藍色更敏感[S型視錐細胞對紫藍色敏感(S來自英語Short - 短波光譜),M -型- 位於光譜的綠黃色(M 來自英語Medium - 中波)部分,L 型- 位於光譜的黃紅色(L 來自英語Long - 長波)部分。這三種視錐細胞(和視桿細胞,對光譜的翠綠色部分敏感)的存在賦予人色覺。 /約。譯]。 ,我們眼睛中的另一種光感受器,能夠偵測亮度的變化,但對顏色更敏感。我們的眼睛大約有 120 億個視桿細胞,而只有 6 萬個視錐細胞。

這就是為什麼我們的眼睛更擅長檢測亮度變化而不是顏色變化。如果將顏色與亮度分開,您可以去除一點顏色,而沒有人會注意到任何東西。色度子取樣是以比亮度分量更低的解析度表示影像色彩分量的過程。在上面的範例中,每個像素恰好具有一個 Y 分量,每個單獨的四個像素組恰好具有一個 Cb 和一個 Cr 分量。因此,圖像包含的顏色資訊比原始圖像少四倍。

YCbCr 色彩空間不僅用於 JPEG。它最初是在 1938 年為電視節目而發明的。並不是每個人都有彩色電視,因此將顏色和亮度分開可以讓每個人都獲得相同的信號,而沒有顏色的電視則僅使用亮度分量。

因此,從編輯器中刪除一個數字會完全破壞所有顏色。元件以 YYYY Cb Cr 的形式儲存(事實上,不一定會按照該順序 - 儲存順序在檔案頭中指定)。刪除第一個數字將導致 Cb 的第一個值被視為 Y,Cr 被視為 Cb,一般來說,您將產生切換圖片所有顏色的骨牌效應。

JPEG 規範並不會強制您使用 YCbCr。但大多數檔案都使用它,因為它可以產生比 RGB 更好的下取樣影像。但你不必相信我的話。在下表中親自查看每個單獨分量的子取樣在 RGB 和 YCbCr 中的樣子。

JPEG 格式的工作原理
(互動版 - 在 原來的 文章)。

藍色的去除不如紅色或綠色的去除那麼明顯。這是因為您的眼睛中有 64 萬個視錐細胞,其中大約 32% 對紅色敏感,2% 對綠色敏感,XNUMX% 對藍色敏感。

Y 分量(左下)的下取樣效果最為明顯。即使是很小的變化也是顯而易見的。

將圖像從 RGB 轉換為 YCbCr 不會減少檔案大小,但確實可以更輕鬆地找到可刪除的不太明顯的細節。有損壓縮發生在第二階段。它基於以更可壓縮的形式呈現數據的想法。

2. 離散餘弦變換與取樣

在很大程度上,這種等級的壓縮就是 JPEG 的全部內容。將顏色轉換為 YCbCr 後,各個分量被單獨壓縮,因此我們可以只關注 Y 分量。這是應用該層後 Y 分量位元組的樣子。

JPEG 格式的工作原理
(互動版 - 在 原來的 文章)。 在互動式版本中,按一下像素會將編輯器捲動到代表該像素的行。嘗試從末尾刪除數字或向某個數字添加幾個零。

乍一看,它看起來壓縮得很糟糕。影像中有 100 個像素,需要 000 個數字來表示它們的亮度(Y 分量)——這比根本不壓縮更糟!

但請注意,這些數字大部分為零。此外,可以在不改變影像的情況下刪除行末尾的所有零。大約還剩下 26 個號碼,這幾乎少了 000 倍!

這一關包含了國際象棋圖案的秘密。與我們所見過的其他效果不同,這些圖案的出現並不是故障。它們是整個圖像的構建塊。編輯器的每一行恰好包含 64 個數字,即與 64 個獨特模式的強度相對應的離散餘弦變換 (DCT) 係數。

這些圖案是根據餘弦圖形成的。以下是其中一些的外觀:

JPEG 格式的工作原理
8 賠率中的 64 賠率

下圖顯示了所有 64 種模式。

JPEG 格式的工作原理
(互動版 - 在 原來的 文章)。

這些圖案特別重要,因為它們構成了 8x8 影像的基礎。如果您不熟悉線性代數,這表示任何 8x8 影像都可以由這 64 個圖案組成。 DCT 是將影像劃分為 8x8 區塊並將每個區塊轉換為這 64 個係數的組合的過程。

任何圖像都可以由 64 種特定圖案組成,這似乎很神奇。然而,這等於說地球上的任何地方都可以用兩個數字來描述—緯度和經度[表示半球/大約。譯]。我們通常認為地球表面是二維的,所以我們只需要兩個數字。 8x8 影像有 64 個維度,因此我們需要 64 個數字。

目前尚不清楚這對壓縮有何幫助。如果我們需要 64 個數字來表示 8x8 影像,為什麼這比僅儲存 64 個亮度分量更好?我們這樣做的原因與將三個 RGB 數字轉換為三個 YCbCr 數字的原因相同:它允許我們刪除微妙的細節。

由於 JPEG 將 DCT 應用於 8x8 區塊,因此很難準確看出在此階段刪除了哪些細節。然而,沒有人禁止我們把它應用到整個畫面上。以下是套用於整個圖片的 Y 分量的 DCT 的樣子:

JPEG 格式的工作原理

可以從末尾刪除超過 60 個數字,而照片幾乎沒有明顯變化。

JPEG 格式的工作原理

但請注意,如果我們將前五個數字歸零,差異將會很明顯。

JPEG 格式的工作原理

開頭的數字代表影像中的低頻變化,我們的眼睛最能捕捉這些變化。接近末尾的數字表示更難以注意到的高頻變化。為了“看到眼睛看不到的東西”,我們可以透過將前 5000 個數字歸零來隔離這些高頻細節。

JPEG 格式的工作原理

我們可以看到影像中每個像素發生最大變化的所有區域。貓的眼睛、鬍鬚、毛圈毯和左下角的陰影都很引人注目。您可以進一步將前 10 個數字清除:

JPEG 格式的工作原理

20 000:

JPEG 格式的工作原理

40 000:

JPEG 格式的工作原理

60 000:

JPEG 格式的工作原理

這些高頻細節在壓縮階段被 JPEG 刪除。將顏色轉換為 DCT 係數不會造成任何損失。損失發生在採樣步驟,其中高頻或接近零的值被刪除。當您降低 JPEG 保存品質時,程式會增加刪除值數量的閾值,這會減少檔案大小,但會使圖片更加像素化。這就是為什麼第一部分中的圖像(小了 57 倍)看起來像這樣。與更高品質的版本相比,每個 8x8 區塊由較少的 DCT 係數表示。

您可以創建像漸變流圖像這樣很酷的效果。您可以顯示模糊的圖片,隨著下載的係數越來越多,該圖片會變得越來越詳細。

這裡只是為了好玩,只使用 24 個數字即可得到以下結果:

JPEG 格式的工作原理

或只是 5000:

JPEG 格式的工作原理

雖然很模糊,但還是能認出來!

3.遊程編碼、delta和Huffman

到目前為止,壓縮的所有階段都是有損的。相反,最後一個階段沒有損失地進行。它不會刪除訊息,但會顯著減小檔案大小。

如何在不遺失資訊的情況下壓縮某些內容?想像一下我們如何描述一個簡單的黑色矩形 700 x 437。

JPEG 為此使用 5000 個數字,但可以獲得更好的結果。您能想像一種編碼方案可以用盡可能少的位元組來描述這樣的圖像嗎?

我能想到的最小方案使用四個:三個表示顏色,第四個表示該顏色有多少個像素。以這種壓縮方式表示重複值的想法稱為遊程編碼。它是無損的,因為我們可以將編碼資料還原為其原始形式。

帶有黑色矩形的 JPEG 檔案遠大於 4 位元組 - 請記住,在 DCT 級別,壓縮應用於 8x8 像素區塊。因此,至少每 64 個像素需要一個 DCT 係數。我們需要一個,因為遊程長度編碼不是儲存一個 DCT 係數後面跟著 63 個零,而是允許我們儲存一個數字並指示「所有其他數字都是零」。

增量編碼是一種技術,其中每個位元組包含與某個值的差異,而不是絕對值。因此,編輯某些位元組會更改所有其他像素的顏色。例如,不是存儲

12 13 14 14 14 13 13 14

我們可以從 12 開始,然後簡單地指出需要加或減多少才能得到下一個數字。增量編碼中的序列採用以下形式:

12 1 1 0 0 -1 0 1

轉換後的資料並不比原始資料小,但更容易壓縮。在行程編碼之前應用增量編碼可以提供很大幫助,同時仍然是無損壓縮。

Delta 編碼是 8x8 區塊之外使用的少數技術之一。在 64 個 DCT 係數中,有一個只是常數波函數(純色)。它代表亮度分量的每個區塊的平均亮度,或Cb分量的平均藍色度,等等。每個 DCT 區塊的第一個值稱為 DC 值,每個 DC 值相對於前一個 DC 值進行增量編碼。因此,改變第一個區塊的亮度將影響所有區塊。

最後的謎團仍然存在:改變單數如何完全破壞整個畫面?到目前為止,壓縮等級還沒有這樣的屬性。答案就在 JPEG 標頭中。前 500 個位元組包含有關圖像的元資料 - 寬度、高度等,但我們尚未使用它們。

如果沒有標頭,則幾乎不可能(或非常困難)解碼 JPEG。看起來好像我正在試圖向你描述這幅畫,並且我開始發明詞彙來傳達我的印象。描述可能會非常簡潔,因為我可以發明具有我想要傳達的含義的單詞,但對其他人來說它們沒有意義。

這聽起來很愚蠢,但事實確實如此。每個 JPEG 影像都使用特定的程式碼進行壓縮。代碼字典儲存在標頭中。這種技術稱為霍夫曼碼,詞彙稱為霍夫曼表。在標頭中,該表用兩個位元組標記 - 255,然後是 196。每個顏色分量都可以有自己的表。

對錶格的更改將從根本上影響任何圖像。一個很好的例子是將第 15 行改為 1。

JPEG 格式的工作原理

發生這種情況是因為表指定了應如何讀取各個位元。到目前為止,我們只處理了十進制形式的二進制數。但這向我們隱藏了這樣一個事實:如果要將數字 1 儲存在一個位元組中,它將看起來像 00000001,因為每個位元組必須恰好有 XNUMX 位,即使只需要其中一位。

如果您有很多小數字,這可能會浪費大量空間。霍夫曼碼是一種技術,可以讓我們放寬每個數字必須佔用八位的要求。這意味著如果您看到兩個位元組:

234 115

然後,根據霍夫曼表,這些可能是三個數字。要提取它們,您需要先將它們分解為單獨的部分:

11101010 01110011

然後我們查看表格找出如何將它們分組。例如,這可能是前六位 (111010) 或十進制的 58,後面跟著五位 (10011) 或 19,最後是最後四位 (0011) 或 3。

因此,要理解這個壓縮階段的位元組是非常困難的。位元組並不代表它們看起來的樣子。我不會在本文中詳細介紹如何使用該表,但是 物料 網路上關於這個問題 夠了.

利用這些知識,您可以做的一個有趣的技巧是將標頭與 JPEG 分開並單獨儲存。事實上,事實證明只有您可以讀取該檔案。 Facebook 這樣做是為了讓文件變得更小。

還可以做的就是對霍夫曼錶進行相當大的更改。對其他人來說,它看起來就像一張破碎的圖片。只有您知道修復它的神奇方法。

讓我們總結一下:那麼解碼 JPEG 需要什麼?必要的:

  1. 從標頭中提取霍夫曼表並解碼位。
  2. 提取每個 8x8 區塊的每個顏色和亮度分量的離散餘弦變換係數,執行逆遊程長度和增量編碼變換。
  3. 根據係數組合餘弦以獲得每個8x8塊的像素值。
  4. 如果執行了子採樣,則縮放顏色分量(此資訊位於標題中)。
  5. 將每個像素的 YCbCr 值轉換為 RGB。
  6. 在螢幕上顯示影像!

只是為了看一張與貓的照片而做的認真的工作!然而,我喜歡它的是它展示了 JPEG 技術是如何以人為本的。它基於我們感知的特殊性,使我們能夠實現比傳統技術更好的壓縮。現在我們了解了 JPEG 的工作原理,我們可以想像如何將這些技術轉移到其他領域。例如,影片中的增量編碼可以顯著減小檔案大小,因為通常存在幀與幀之間不發生變化的整個區域(例如背景)。

文章中使用的程式碼,已打開,包含有關如何用自己的圖片替換圖片的說明。

來源: www.habr.com

添加評論