图像相似度评价指标

图像相似度评价指标

在图像处理中我们经常遇到需要评价两张图像是否相似,给出其相似度的指标,这里总结了三种评判指标均方误差MSE, 结构相似性SSIM, 以及峰值信噪比PSNR, 分三个小结介绍其原理以及对应的matlab以及tensorflow版本的算法实现。


均方误差MSE

即m×n单色图像 I 和 K(原图像与处理图像)之间均方误差,定义为:


MSE formula

Matlab实现

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

Tensorflow实现

# 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

结构相似性SSIM

  1. 结构相似性:
    自然图像具有极高的结构性,表现在图像的像素间存在着很强的相关性,尤其是在空间相似的情况下。这些相关性在视觉场景中携带着关于物体结构的重要信息。我们假设人类视觉系统(HSV)主要从可视区域内获取结构信息。所以通过探测结构信息是否改变来感知图像失真的近似信息。
    大多数的基于误差敏感度(error sensitivity)的质量评估方法(如MSE,PSNR)使用线性变换来分解图像信号,这不会涉及到相关性。我们要讨论的SSIM就是要找到更加直接的方法来比较失真图像和参考图像的结构。
  2. SSIM指数
    物体表面的亮度信息与照度和反射系数有关,且场景中的物体的结构与照度是独立的,反射系数与物体有关。我们可以通过分离照度对物体的影响来探索一张图像中的结构信息。这里,把与物体结构相关的亮度和对比度作为图像中结构信息的定义。因为一个场景中的亮度和对比度总是在变化的,所以我们可以通过分别对局部的处理来得到更精确的结果。

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


SSIM测量系统

SSIM的求解公式如下:


SSIM formula

其中u_xx的平均值,u_yy的平均值,σ_xx的方差,σ_yy的方差,σ_{xy}xy的协方差。c_1=(k_1*L)^2c_2=(k_2*L)^2是用来维持稳定的常数。L是像素值的动态范围。k_1=0.01,k_2=0.03
结构相似性的范围为-1到+1(即SSIM∈(-1, 0])。当两张图像一模一样时,SSIM的值等于1。

Matlab实现

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为灰度级数,L=255
    %-------------------------------------------------------------------
    %     ima - 比较图像A
    %     imb - 比较图像B
    %
    % ssim_map - 各加窗后得到的SSIM(A,B|w)组成的映射矩阵
    %    mssim - 对加窗得到的SSIM(A,B|w)求平均,即最终的SSIM(A,B)
    %  siga_sq - 图像A各窗口内灰度值的方差
    %  sigb_sq - 图像B各窗口内灰度值的方差
    %-------------------------------------------------------------------
    %  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');%对窗口内并没有进行平均处理,而是与高斯卷积,
    ub   = filter2(w, imb, 'valid'); % 类似加权平均
    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实现

# 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考虑使用下面函数

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

具体使用方式参考:传送门


峰值信噪比PSNR

PSNR本质上与MSE相同,是MSE的对数表示。

峰值信噪比PSNR衡量图像失真或是噪声水平的客观标准。2个图像之间PSNR值越大,则越相似。普遍基准为30dB,30dB以下的图像劣化较为明显。定义为:


PSNR formula

Matlab实现

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实现

# 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. 经有情人士质疑SSIM的取负值情况不存在,考虑使用matlab进行下面的代码测#试:
    [1]: > matlab [^_^]: >A(:,:) = round(255*rand(100,100)); [^_^]: >B(:,:) = abs(255 - A(:,:)); [^_^]: >[mssim, ssimmap, siga_sq,sigb_sq] = ssim(A, B); [^_^]: >

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,639评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,093评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,079评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,329评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,343评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,047评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,645评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,565评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,201评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,338评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,014评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,701评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,194评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,685评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,345评论 2 358

推荐阅读更多精彩内容