JPEG編解碼原理

一.JPEG簡介

JPEG全稱Joint Photographic Experts Group(聯(lián)合圖像專家組),它是一項數(shù)字圖像壓縮標準(ISO/IEC 10918),1992年提出。
JPEG是一種有損壓縮的數(shù)字圖像技術(shù),它的核心算法是離散余弦變換(DCT)。

二.JPEG壓縮技術(shù)

JPEG編碼原理涉及到一些圖像處理的知識,強烈推薦先看一下:圖像與濾波。

JPEG編碼過程如下圖
[圖片上傳失敗...(image-c3fa31-1583587032871)]
解碼過程就是編碼的逆向操作

[圖片上傳失敗...(image-2ad7ec-1583587032871)]

2.1 塊切割

JPEG標準在處理圖片時會先把圖片分割成一個個8x8像素的方塊,后面的DCT、量化、熵編碼都是針對單個方塊的操作,編碼的產(chǎn)物是這些方塊的壓縮數(shù)據(jù)。壓縮數(shù)據(jù)經(jīng)過解碼還原成像素數(shù)據(jù),然后將一個個方塊拼成一整完整圖片的像素數(shù)據(jù)送給顯卡展示。

2.2 DCT

DCT(Discrete Cosine Transform)變換的全稱是離散余弦變換,它能將時域信號轉(zhuǎn)換成頻域信號,其中低頻部分集中在矩陣的左上角,高頻部分集中在矩陣的右下角。它是傅里葉變換的一種變種,相比傅里葉變換,DCT變換函數(shù)只用實數(shù),算法實現(xiàn)簡單,所以廣泛運用在圖片壓縮領(lǐng)域,JPEG就采用了二維DCT變換。

由于人眼對圖片中的低頻信息(色彩變化不明顯,如圖片的整體色調(diào),物體輪廓)比較敏感,對高頻信息不敏感(色彩變化劇烈,如物體的邊緣、人臉上的小斑點),因此我們可以利用DCT變換把圖片中高頻和低頻部分區(qū)分開來,然后將高頻部分的數(shù)據(jù)進行壓縮,這樣就達到壓縮圖片的功能。

二維DCT變換的公式為:

image
  • F(u, v) 代表DCT變換后坐標(u, v)的頻率
  • c(u)、c(v)可以認為是一個補償系數(shù),可以使DCT變換矩陣為正交矩陣
  • f(i, j) 代表坐標(i, j)的像素數(shù)據(jù)



假如我們有一個8x8的像素數(shù)據(jù):

image

運用DCT公式,我們把像素信號轉(zhuǎn)換成如下頻率信號:

image

左上區(qū)域存儲的是低頻信號,右下區(qū)域存儲的是高頻信號

2.2 量化

下面我們用一個50% quantily的JPEG量化表將頻率數(shù)據(jù)量化:

image

量化公式如下:

  • B(i, j) = round(G(i, j) / Q(i, j))

如:Q(0, 0) = round(-415.38 / 16) = -26
Q(0, 1) = round(-30.19 / 11) = -3

所謂量化其實就是將頻率/量化步長,將量化步長以內(nèi)的精度信息丟失??梢杂^察到上表的左上角數(shù)值小,右下角數(shù)值大,因此這張量化表的作用就是屏蔽高頻信息。最終的量化結(jié)果為:

image

2.3 熵編碼

熵編碼是一類編碼規(guī)范,它要求編碼過程中按熵原理不丟失任何信息。常見的熵編碼有:香農(nóng)編碼、哈夫曼編碼和算術(shù)編碼。
JPEG先用RLE(run-length encoding,游程編碼)編碼將圖像數(shù)據(jù)以“之字形”排列,如下圖,這樣可以盡可能的將頻率為0的數(shù)據(jù)存儲在一起。連續(xù)N個0,可以用一個0和一個長度N來表示,壓縮效果很好,然后將剩下的位置使用霍夫曼編碼。

image

以上就是JPEG編碼的重要步驟。解碼基本上就是上述步驟的逆向操作,就不多說了,這里只介紹一下IDCT

2.4 IDCT

IDCT即Inverse DCT,它就是DCT的逆向操作,將圖像的頻率數(shù)據(jù)轉(zhuǎn)換成像素數(shù)據(jù),公式如下:

image
  • f(i, j) 坐標(i, j)的像素數(shù)據(jù)
  • F(u, v) 坐標(u, v)的頻率數(shù)據(jù)
  • c(u)、c(v)可以認為是一個補償系數(shù),可以使DCT變換矩陣為正交矩陣

還是看上面的例子,我們先做一下反量化操作,即乘一下步長就可以了:

image

接著我們將上圖的頻率數(shù)據(jù)代入IDCT公式,最終我們得到還原后的像素數(shù)據(jù):

image

三.Android實例

下面我們通過一個Android實例來看一下DCT轉(zhuǎn)換的效果
為了方便理解,我這里用一張Y分量的yuv圖片來演示,原圖如下

image

二維DCT變換公式其實是一個矩陣變換公式,上面的公式是它的求和形式,效率比較低。開發(fā)中一般直接用矩陣運算替代,公式如下:

image
image

其中X為yuv像素矩陣,Y為頻域信號矩陣

3.1 DCT變換

這里引用了apache的commons-math3庫來做矩陣運算

    // dct變換
    public static RealMatrix dct2(byte[] yuv, int N) {
        // 拷貝N*N的Y分量
        byte[] y = new byte[N * N];
        System.arraycopy(yuv, 0, y, 0, y.length);
        // 一維數(shù)組轉(zhuǎn)成二維數(shù)組
        double[][] matrixData = MatrixUtils.toMatrixData(y, N);
        // 構(gòu)造yuv矩陣
        RealMatrix signalMatrix = new Array2DRowRealMatrix(matrixData);
        // 獲取dct系數(shù)矩陣
        RealMatrix dctMatrix = getDCTMatrix(N);
        // 頻域矩陣 = dct系統(tǒng)矩陣 * yuv矩陣 * dct系數(shù)轉(zhuǎn)置矩陣 
        RealMatrix frequencyMatrix = dctMatrix.multiply(signalMatrix).multiply(dctMatrix.transpose());
        return frequencyMatrix;
    }
    
    // 獲取dct系數(shù)矩陣
    private static RealMatrix getDCTMatrix(int N) {
        double matrixData[][] = new double[N][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                double factor = i == 0 ? Math.sqrt(1d / N) : Math.sqrt(2d / N);
                matrixData[i][j] = factor * Math.cos((2 * j + 1) * i * Math.PI * 0.5d / N);
            }
        }
        return new Array2DRowRealMatrix(matrixData);
    }    

變換之后效果如下:

image

3.2 IDCT變換

DCT反變換公式如下:

image
 // dct反變換
 public static double[][] idct2(RealMatrix frequencyMatrix, int N) {
        // 獲取dct系數(shù)矩陣
        RealMatrix dctMatrix = getDCTMatrix(N);
        // 頻域矩陣 = dct系數(shù)轉(zhuǎn)置矩陣 * dct系統(tǒng)矩陣 * yuv矩陣
        RealMatrix frequencyMatrix = dctMatrix.transpose().multiply(frequencyMatrix).multiply(dctMatrix);
        return signalMatrix;
    }

變換效果就是把上面的頻域信號轉(zhuǎn)成yuv信號,效果就跟原圖一樣(DCT變換過程是無損的,忽略運算過程中的誤差)

3.3 分塊DCT變換

將圖片分為一個個8x8的方塊,分別對這些方塊做dct變換,代碼就不展示了,直接看效果

image

3.4 量化

這里依然用JPEG 50% quantily量化表,效果如下

image

3.5 分塊反DCT變換

將量化后的一個個8x8方塊依次做IDCT變換,再拼成一整完整的圖片


image

左邊是原圖,右邊是量化之后的圖,仔細看還是能發(fā)現(xiàn)右圖有一些毛邊,細節(jié)上不如左圖清晰

項目地址:
Gitee:https://gitee.com/huaisu2020/Android-Live
Github:https://github.com/xh2009cn/Android-Live

參考文章:
http://www.ruanyifeng.com/blog/2017/12/image-and-wave-filters.html
https://en.wikipedia.org/wiki/JPEG

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • * 音視頻入門文章目錄 *[https://www.ihubin.com/blog/audio-video-bas...
    binglingziyu閱讀 889評論 0 2
  • JPEG文件的存儲格式有很多種,但最常用的是JFIF格式,即JPEG File Interchange Forma...
    hehtao閱讀 9,663評論 1 7
  • (文章還剩實踐部分沒寫,答辯過后補上...)JPEG文件在當下數(shù)字化生活中是無處不在的,但是在熟悉的JPEG面紗背...
    MrYun閱讀 457評論 0 0
  • ### YUV顏色空間 視頻是由一幀一幀的數(shù)據(jù)連接而成,而一幀視頻數(shù)據(jù)其實就是一張圖片。 yuv是一種圖片儲存格式...
    天使君閱讀 3,671評論 0 4
  • 姓名:李偉 學(xué)號:17101223393 【嵌牛導(dǎo)讀】:大家對JPEG了解嗎?今天和大家分享一下。 【嵌牛鼻子...
    LW_e565閱讀 3,053評論 0 1

友情鏈接更多精彩內(nèi)容