psnr
作為圖像質量評價指標,在很多圖像領域如圖像超分辨率、圖像壓縮、圖像去噪等都有廣泛的應用。
Peak signal-to-noise ratio(簡稱PSNR)是一個工程術語,表示信號的最大可能功率與影響信號表示精度的干擾噪聲功率之間的比值。由于許多信號都有非常寬的動態范圍,峰值訊噪比常用對數分貝單位來表示。
它常簡單地通過均方誤差(MSE)進行定義。兩個 m×nm×nm×n 單色圖像 III 和 KKK , III 為一無噪聲的原始圖像,KKK 為 III 的噪聲近似(例: III 為未壓縮的原始圖像,KKK為 III 經過壓縮后的圖像),那么它們的的均方誤差定義為:
MSE=1mn∑i=0m?1∑j=0n?1[I(i,j)?K(i,j)]2{\displaystyle {\mathit {MSE}}={\frac {1}{mn}}\sum _{i=0}^{m-1}\sum _{j=0}^{n-1}[I(i,j)-K(i,j)]^{2}} MSE=mn1?i=0∑m?1?j=0∑n?1?[I(i,j)?K(i,j)]2
峰值信噪比定義為:
PSNR=10?log?10(MAXI2MSE)=20?log?10(MAXIMSE){\displaystyle {\mathit {PSNR}}=10\cdot \log _{10}\left({\frac {{\mathit {MAX}}_{I}^{2}}{\mathit {MSE}}}\right)=20\cdot \log _{10}\left({\frac {{\mathit {MAX}}_{I}}{\sqrt {\mathit {MSE}}}}\right)} PSNR=10?log10?(MSEMAXI2??)=20?log10?(MSE?MAXI??)
其中,MAXIMAX_{I}MAXI? 是表示圖像點顏色的最大數值,如果每個采樣點用 8 位表示(例:影像處理),那么就是 255。更為通用的表示是,如果每個采樣點用 B 位線性脈沖編碼調制表示,那么 MAXIMAX_{I}MAXI? 就是:
2B?1{\displaystyle 2^{B}-1} 2B?1
對于每點有RGB三個值的彩色圖像來說,峰值信噪比的定義類似。除了橫軸、縱軸 mmm 和 nnn 以外,還要考慮它的顏色組成RGB。我們需要分別對每個顏色處理其MSE,因為有3個顏色通道,所以MSE需再除以3。
彩色圖像的峰值訊噪比定義為:
PSNR=10?log?10(MAXI213mn∑R,G,B∑i=0m?1∑j=0n?1[Icolor(i,j)?Kcolor(i,j)]2){\displaystyle {\mathit {PSNR}}=10\cdot \log _{10}\left({\frac {{\mathit {MAX}}_{I}^{2}}{{\frac {1}{3mn}}\sum _{R,G,B}^{}\sum _{i=0}^{m-1}\sum _{j=0}^{n-1}[I_{color}(i,j)-K_{color}(i,j)]^{2}}}\right)} PSNR=10?log10?(3mn1?∑R,G,B?∑i=0m?1?∑j=0n?1?[Icolor?(i,j)?Kcolor?(i,j)]2MAXI2??)
python簡單代碼,這是我一開始寫的代碼,兩個地方有點問題,也是大家常會犯的錯誤。
from PIL import Image
import numpy as npimg1 = np.array(Image.open('original.jpg'))
img2 = np.array(Image.open('compress.jpg'))def psnr(img1, img2):mse = np.mean((img1-img2)**2)if mse == 0:return 100else:return 20*np.log10(255/np.sqrt(mse))if __name__ == "__main__":print(psnr(img1, img2))
1、如果mse == 0
不應該返回100
,而是正無窮,正無窮在python中用float('inf')
表示。(參考維基英文百科:In the absence of noise, the two images III and KKK are identical, and thus the MSE is zero. In this case the PSNR is infinite.)
2、數據類型的問題。img1
和img2
原本是np.int8
類型,應該轉換為np.float64
再參與計算,否則會導致精度丟失,計算的psnr
值偏大。(這里參考了psnr百科詞條中的matlab代碼實現,代碼中對圖片進行了double
操作,學過matlab的同學應該清楚,這就是將無符號int8類型
轉換為雙精度浮點型
)
修改后的代碼:
from PIL import Image
import numpy as npimg1 = np.array(Image.open('original.jpg')).astype(np.float64)
img2 = np.array(Image.open('compress.jpg')).astype(np.float64)def psnr(img1, img2):mse = np.mean((img1-img2)**2)if mse == 0:return float('inf')else:return 20*np.log10(255/np.sqrt(mse))if __name__ == "__main__":print(psnr(img1, img2))
如果你不想自己寫,也可以調用第三方庫skimage
實現,里面有封裝好的計算psnr
的代碼,和我修改后的代碼計算結果是一模一樣的,具體調用方式如下:
from skimage.metrics import peak_signal_noise_ratio as psnr
from PIL import Image
import numpy as npimg1 = np.array(Image.open('original.jpg'))
img2 = np.array(Image.open('compress.jpg'))if __name__ == "__main__":print(psnr(img1, img2))
python 類,備注:skimage的大名叫scikit-image,安裝請用pip install scikit-image
。
同壓縮比例的PSNR比較(點擊圖片可放大)圖片為臺灣桃園國際機場停機坪 | |||
---|---|---|---|
未壓縮的原圖 | PSNR 47.61dB | PSNR 34.02dB | PSNR 24.46dB |
psnr的matlab實現:
function PSNR = psnr(f1, f2)
%計算兩幅圖像的峰值信噪比
k = 8;
%k為圖像是表示地個像素點所用的二進制位數,即位深。
fmax = 2.^k - 1;
a = fmax.^2;
MSE =(double(im2uint8(f1)) -double( im2uint8(f2))).^2;
b = mean(mean(MSE));
PSNR = 10*log10(a/b);
【python】ssim原理簡介及代碼實現
https://zh.wikipedia.org/wiki/峰值信噪比
https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
https://baike.baidu.com/item/psnr/2925132
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态