圖像相似度評價(jià)指標(biāo)

圖像相似度評價(jià)指標(biāo)

在圖像處理中我們經(jīng)常遇到需要評價(jià)兩張圖像是否相似做鹰,給出其相似度的指標(biāo)立莉,這里總結(jié)了三種評判指標(biāo)均方誤差MSE, 結(jié)構(gòu)相似性SSIM, 以及峰值信噪比PSNR, 分三個(gè)小結(jié)介紹其原理以及對應(yīng)的matlab以及tensorflow版本的算法實(shí)現(xiàn)昨悼。


均方誤差MSE

即m×n單色圖像 I 和 K(原圖像與處理圖像)之間均方誤差捣辆,定義為:


MSE formula

Matlab實(shí)現(xiàn)

function MSE = mse(I, K)
    [M,N,D] = size(I);
    Diff = double(I)-double(K);
    MSE = sum(Diff(:).^2)/numel(I);
end

Tensorflow實(shí)現(xiàn)

# import tensorflow as tf


def MSE(I, K):
    x, y = tf.cast(I, tf.float32), tf.cast(K, tf.float32)
    mse = tf.losses.mean_squared_error(labels=y, predictions=x)
    return mse

結(jié)構(gòu)相似性SSIM

  1. 結(jié)構(gòu)相似性:
    自然圖像具有極高的結(jié)構(gòu)性换况,表現(xiàn)在圖像的像素間存在著很強(qiáng)的相關(guān)性欠气,尤其是在空間相似的情況下厅各。這些相關(guān)性在視覺場景中攜帶著關(guān)于物體結(jié)構(gòu)的重要信息。我們假設(shè)人類視覺系統(tǒng)(HSV)主要從可視區(qū)域內(nèi)獲取結(jié)構(gòu)信息预柒。所以通過探測結(jié)構(gòu)信息是否改變來感知圖像失真的近似信息队塘。
    大多數(shù)的基于誤差敏感度(error sensitivity)的質(zhì)量評估方法(如MSE,PSNR)使用線性變換來分解圖像信號,這不會涉及到相關(guān)性宜鸯。我們要討論的SSIM就是要找到更加直接的方法來比較失真圖像和參考圖像的結(jié)構(gòu)憔古。
  2. SSIM指數(shù)
    物體表面的亮度信息與照度和反射系數(shù)有關(guān),且場景中的物體的結(jié)構(gòu)與照度是獨(dú)立的顾翼,反射系數(shù)與物體有關(guān)投放。我們可以通過分離照度對物體的影響來探索一張圖像中的結(jié)構(gòu)信息。這里适贸,把與物體結(jié)構(gòu)相關(guān)的亮度和對比度作為圖像中結(jié)構(gòu)信息的定義灸芳。因?yàn)橐粋€(gè)場景中的亮度和對比度總是在變化的,所以我們可以通過分別對局部的處理來得到更精確的結(jié)果拜姿。

SSIM的算法流程圖原理圖如下所示:


SSIM測量系統(tǒng)

SSIM的求解公式如下:


SSIM formula

其中u_xx的平均值烙样,u_yy的平均值,σ_xx的方差蕊肥,σ_yy的方差谒获,σ_{xy}xy的協(xié)方差。c_1=(k_1*L)^2壁却,c_2=(k_2*L)^2是用來維持穩(wěn)定的常數(shù)批狱。L是像素值的動態(tài)范圍。k_1=0.01,k_2=0.03展东。
結(jié)構(gòu)相似性的范圍為-1到+1(即SSIM∈(-1, 0])赔硫。當(dāng)兩張圖像一模一樣時(shí),SSIM的值等于1盐肃。

Matlab實(shí)現(xiàn)

function [mssim, ssim_map,siga_sq,sigb_sq] = SSIM(ima, imb)
    % ========================================================================
    %ssim的算法主要參考如下論文:
    %Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image
    % quality assessment: From error visibility to structural similarity,"
    % IEEE Transactios on Image Processing, vol. 13, no. 4, pp. 600-612,
    % Apr. 2004.
    %  首先對圖像加窗處理爪膊,w=fspecial('gaussian', 11, 1.5);
    %                 (2*ua*ub+C1)*(2*sigmaa*sigmab+C2)
    %   SSIM(A,B)=——————————————————————————————————————————————————
    %              (ua*ua+ub*ub+C1)(sigmaa*sigmaa+sigmab*sigmab+C2)
    %     C1=(K1*L);
    %     C2=(K2*L);   K1=0.01,K2=0.03
    %     L為灰度級數(shù)砸王,L=255
    %-------------------------------------------------------------------
    %     ima - 比較圖像A
    %     imb - 比較圖像B
    %
    % ssim_map - 各加窗后得到的SSIM(A,B|w)組成的映射矩陣
    %    mssim - 對加窗得到的SSIM(A,B|w)求平均推盛,即最終的SSIM(A,B)
    %  siga_sq - 圖像A各窗口內(nèi)灰度值的方差
    %  sigb_sq - 圖像B各窗口內(nèi)灰度值的方差
    %-------------------------------------------------------------------
    %  Cool_ben
    %=======================================================================

    w = fspecial('gaussian', 11, 1.5);  %window 加窗
    K(1) = 0.01;
    K(2) = 0.03;
    L = 255;
    ima = double(ima);
    imb = double(imb);

    C1 = (K(1)*L)^2;
    C2 = (K(2)*L)^2;
    w = w/sum(sum(w));

    ua   = filter2(w, ima, 'valid');%對窗口內(nèi)并沒有進(jìn)行平均處理,而是與高斯卷積谦铃,
    ub   = filter2(w, imb, 'valid'); % 類似加權(quán)平均
    ua_sq = ua.*ua;
    ub_sq = ub.*ub;
    ua_ub = ua.*ub;
    siga_sq = filter2(w, ima.*ima, 'valid') - ua_sq;
    sigb_sq = filter2(w, imb.*imb, 'valid') - ub_sq;
    sigab = filter2(w, ima.*imb, 'valid') - ua_ub;

    ssim_map = ((2*ua_ub + C1).*(2*sigab + C2))./((ua_sq + ub_sq + C1).*(siga_sq + sigb_sq + C2));

    mssim = mean2(ssim_map);

end

Tensorflow實(shí)現(xiàn)

# import tensorflow as tf


def _tf_fspecial_gauss(size, sigma):
    """Function to mimic the 'fspecial' gaussian MATLAB function"""
    x_data, y_data = np.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]

    x_data = np.expand_dims(x_data, axis=-1)
    x_data = np.expand_dims(x_data, axis=-1)

    y_data = np.expand_dims(y_data, axis=-1)
    y_data = np.expand_dims(y_data, axis=-1)

    x = tf.constant(x_data, dtype=tf.float32)
    y = tf.constant(y_data, dtype=tf.float32)

    g = tf.exp(-((x**2 + y**2)/(2.0*sigma**2)))
    return g / tf.reduce_sum(g)


def tf_ssim(img1, img2, cs_map=False, mean_metric=True, size=11, sigma=1.5):
    window = _tf_fspecial_gauss(size, sigma)    # window shape [size, size]
    K1 = 0.01
    K2 = 0.03
    L = 1  # depth of image (255 in case the image has a different scale)
    C1 = (K1*L)**2
    C2 = (K2*L)**2
    mu1 = tf.nn.conv2d(img1, window, strides=[1, 1, 1, 1], padding='VALID')
    mu2 = tf.nn.conv2d(img2, window, strides=[1, 1, 1, 1], padding='VALID')
    mu1_sq = mu1*mu1
    mu2_sq = mu2*mu2
    mu1_mu2 = mu1*mu2
    sigma1_sq = tf.nn.conv2d(img1*img1, window, strides=[1, 1, 1, 1], padding='VALID') - mu1_sq
    sigma2_sq = tf.nn.conv2d(img2*img2, window, strides=[1, 1, 1, 1], padding='VALID') - mu2_sq
    sigma12 = tf.nn.conv2d(img1*img2, window, strides=[1, 1, 1, 1], padding='VALID') - mu1_mu2
    if cs_map:
        value = (((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1) *
                                                      (sigma1_sq + sigma2_sq + C2)),
                 (2.0*sigma12 + C2)/(sigma1_sq + sigma2_sq + C2))
    else:
        value = ((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1) *
                                                     (sigma1_sq + sigma2_sq + C2))

    if mean_metric:
        value = tf.reduce_mean(value)
    return value


def tf_ms_ssim(img1, img2, mean_metric=True, level=5):
    weight = tf.constant([0.0448, 0.2856, 0.3001, 0.2363, 0.1333], dtype=tf.float32)
    mssim = []
    mcs = []
    for l in range(level):
        ssim_map, cs_map = tf_ssim(img1, img2, cs_map=True, mean_metric=False)
        mssim.append(tf.reduce_mean(ssim_map))
        mcs.append(tf.reduce_mean(cs_map))
        filtered_im1 = tf.nn.avg_pool(img1, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
        filtered_im2 = tf.nn.avg_pool(img2, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
        img1 = filtered_im1
        img2 = filtered_im2

    # list to tensor of dim D+1
    mssim = tf.stack(mssim, axis=0)
    mcs = tf.stack(mcs, axis=0)

    value = (tf.reduce_prod(mcs[0:level-1]**weight[0:level-1])*(mssim[level-1]**weight[level-1]))

    if mean_metric:
        value = tf.reduce_mean(value)
    return value

或者耘成,emm,Tensorflow r1.8考慮使用下面函數(shù)

tf.image.ssim(
    img1,
    img2,
    max_val
)

具體使用方式參考:傳送門


峰值信噪比PSNR

PSNR本質(zhì)上與MSE相同,是MSE的對數(shù)表示凿跳。

峰值信噪比PSNR衡量圖像失真或是噪聲水平的客觀標(biāo)準(zhǔn)件豌。2個(gè)圖像之間PSNR值越大,則越相似控嗜。普遍基準(zhǔn)為30dB,30dB以下的圖像劣化較為明顯骡显。定義為:


PSNR formula

Matlab實(shí)現(xiàn)

function [PSNR, MSE]=psnr(I,K)
    [M,N,D] = size(I);
    Diff = double(I)-double(K);
    MSE = sum(Diff(:).^2)/numel(I);
    PSNR=10*log10(255^2/MSE);
end

Tensorflow實(shí)現(xiàn)

# import tensorflow as tf


def PSNR(I, K):
    x, y = tf.cast(I, tf.float32), tf.cast(K, tf.float32)
    mse = tf.losses.mean_squared_error(labels=y, predictions=x)
    psnr = 10*tf.log(255**2/mse)/tf.log(10)
    return psnr

  1. 經(jīng)有情人士質(zhì)疑SSIM的取負(fù)值情況不存在疆栏,考慮使用matlab進(jìn)行下面的代碼測#試:
    [1]: > matlab [^_^]: >A(:,:) = round(255*rand(100,100)); [^_^]: >B(:,:) = abs(255 - A(:,:)); [^_^]: >[mssim, ssimmap, siga_sq,sigb_sq] = ssim(A, B); [^_^]: >

    ?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惫谤,隨后出現(xiàn)的幾起案子壁顶,更是在濱河造成了極大的恐慌,老刑警劉巖溜歪,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件若专,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝴猪,警方通過查閱死者的電腦和手機(jī)调衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來自阱,“玉大人嚎莉,你說我怎么就攤上這事∨嫱悖” “怎么了趋箩?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長加派。 經(jīng)常有香客問我叫确,道長,這世上最難降的妖魔是什么芍锦? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任竹勉,我火速辦了婚禮,結(jié)果婚禮上醉旦,老公的妹妹穿的比我還像新娘饶米。我一直安慰自己,他們只是感情好车胡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布檬输。 她就那樣靜靜地躺著,像睡著了一般匈棘。 火紅的嫁衣襯著肌膚如雪丧慈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音逃默,去河邊找鬼鹃愤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛完域,可吹牛的內(nèi)容都是我干的软吐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼吟税,長吁一口氣:“原來是場噩夢啊……” “哼凹耙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肠仪,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肖抱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后异旧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體意述,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年吮蛹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荤崇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡匹涮,死狀恐怖天试,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情然低,我是刑警寧澤喜每,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站雳攘,受9級特大地震影響带兜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吨灭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一刚照、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喧兄,春花似錦无畔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拯辙,卻和暖如春郭变,著一層夾襖步出監(jiān)牢的瞬間颜价,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工诉濒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留周伦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓未荒,卻偏偏與公主長得像专挪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子片排,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容