Just a Computer Graphics Studio & My Life

在瞭解峰值信號雜訊比 (Peak Signal to Noise Ratio)定義之後,接下來當然就來驗證它的威力~

在此我特地找了png檔(無損壓縮)的影像,用nEOiMAGING影像處理軟體,將它另存為jpg檔(有損壓縮)的影像,其中jpg又有分壓縮品質。用肉眼也許看不太出來其中的差異,然而卻很容易從檔案大小看出端倪,壓縮品質越差,檔案大小越小。

landscape

原始影像png:314KB

除了從檔案大小可以知道影像品質的差異,我們還可以從PSNR這個衡量方法來驗證,定義可以參考峰值信號雜訊比 (Peak Signal to Noise Ratio)。這裡只列出公式:

PSNR PSNR - MSE

Peak就是指8 bits表示法的最大值255。MSE指 Mean Square Error,In指原始影像第n個pixel值,Pn指經處理後的影像第n個pixel值。PSNR的單位為dB。

/**
	Theme: PSNR (Peak Signal to Noise Ratio)
	compiler: Dev C++ 4.9.9.2
	Library: OpenCV 2.0
	Date: 102/01/06
	Author: HappyMan
	Blog: https://cg2010studio.wordpress.com/
*/
#include <cv.h>
#include <highgui.h>
#include<iostream>

using namespace std;

int main(){
 	IplImage *src1= cvLoadImage("landscape.png");
 	IplImage *src2= cvLoadImage("landscape100Q.jpg");

 	long long int sigma = 0;
 	double MSE = 0.0;
 	double PSNR = 0.0;
 	int frameSize = src1->height*src1->width*3;
 	int blue1=0, blue2=0;
 	int green1=0, green2=0;
 	int red1=0, red2=0;

	// width x height -> [height][width]
    for(int i=0;i<src1->height;i++){
        for(int j=0;j<src1->widthStep;j=j+3){
			blue1=(int)(uchar)src1->imageData[i*src1->widthStep+j];//Blue
			green1=(int)(uchar)src1->imageData[i*src1->widthStep+j+1];//Green
			red1=(int)(uchar)src1->imageData[i*src1->widthStep+j+2];//Red
			blue2=(int)(uchar)src2->imageData[i*src2->widthStep+j];//Blue
			green2=(int)(uchar)src2->imageData[i*src2->widthStep+j+1];//Green
			red2=(int)(uchar)src2->imageData[i*src2->widthStep+j+2];//Red
			sigma+=(blue1-blue2)*(blue1-blue2)+
			(green1-green2)*(green1-green2)+
			(red1-red2)*(red1-red2);
        }
    }
    MSE=sigma/(double)frameSize;
    PSNR=10*log10(255*255/MSE);

	cout<<"sigma: "<<sigma<<endl;;
	cout<<"MSE: "<<MSE<<endl;;
	cout<<"PSNR: "<<PSNR<<endl;;

	system("pause");
	cvWaitKey(0);
	return EXIT_SUCCESS;
}

我實驗幾張圖,分別由png檔轉存jpg檔為不同壓縮品質(100%+High Quality、100%、90%、60%、30%、10%),再與png檔做比較。

執行結果:

landscape100Q

100%+高品質壓縮影像jpg:380KB

100%+High Quality:
sigma: 339922
MSE: 0.491785
PSNR: 51.213
請按任意鍵繼續 . . .

landscape100

100%壓縮影像jpg:209KB

100%:
sigma: 16337462
MSE: 23.6364
PSNR: 34.395
請按任意鍵繼續 . . .

landscape90

90%壓縮影像jpg:73KB

90%:
sigma: 25189183
MSE: 36.4427
PSNR: 32.5147
請按任意鍵繼續 . . .

landscape60

60%壓縮影像jpg:27KB

60%:
sigma: 56718531
MSE: 82.0581
PSNR: 28.9896
請按任意鍵繼續 . . .

landscape30

30%壓縮影像jpg:15KB

30%:
sigma: 75184622
MSE: 108.774
PSNR: 27.7656
請按任意鍵繼續 . . .

landscape10

10%壓縮影像jpg:2KB

10%:
sigma: 110296808
MSE: 159.573
PSNR: 26.1012
請按任意鍵繼續 . . .

比較讓我好奇的是100%+高品質壓縮影像jpg的檔案大小,居然比原始影像png的檔案大!

通常PSNR值越高表示品質越好,一般而言當PSNR的值<30db時,代表以人的肉眼看起來是不能容忍的範圍。因此大部分PSNR值皆要>30db。但PSNR高,並不代表影像品質一定好,有時候還是必須靠人的肉眼輔助來判斷影像的品質才較為正確。

JPGPNG主要差異為何呢?這裡引述他人翻譯WiKi的幾段話:

JPEG在面對自然影像的時候,由於是採用失真壓縮演算法,因此壓縮率比PNG還要大。簡單來說,如果一張風景照片 你用JPG來存,需要1MB 的話,用PNG就要5MB~10MB,雖然PNG檔案較大但是在視覺品質上面並沒有顯著的優越。

PNG在處理包含文字、線條和明顯輪廓的影像則較JPG來的優越,當影像有明顯輪廓邊緣,JPG的失真演算法在處理這種邊緣上就會產生瑕疵,PNG採用無失真演算法,因此影像品質較佳。

若影像儲存在未來是需要更進一步的編輯修改的話則PNG是比較好的選擇,若是用JPG不斷的存取編輯,那麼圖像的品質就越來越差了。當影像已經編輯完畢準備散發傳播的話,JPG則可以幫你縮小體積,卻不損失太多的畫質。

參考:WiKi – JPG、WiKi – PNG利用OpenCV計算灰度圖像的峰值信噪比(PSNR)在DEV-C++環境使用OpenCV-2.1.0-win32-vs2008計算PSNR範例[程式碼篇]該用 PNG 還是 JPG 來存螢幕截圖

Advertisements

Comments on: "[OpenCV] 峰值信號雜訊比 (Peak Signal to Noise Ratio)" (7)

  1. 請問一下成是第22行的
    int frameSize = src1->height*src1->width*3;

    這個應該是只圖像的大小吧?
    為什麼還要在後面乘以三呢?

    喜歡

  2. […] 在瞭解結構相似性 (Structural SIMilarity)後,接下來就是驗證它的效果~我使用和峰值信號雜訊比 (Peak Signal to Noise Ratio)同樣的影像來示範。 […]

    喜歡

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: