MSE 计算模型的预测 Ŷ 与真实标签 Y 的接近程度。公式表示为:
对于两个m×n的单通道图像I和K,它们的均方误差可定义为:
优点:MSE的函数曲线光滑、连续,处处可导,便于使用梯度下降算法,是一种常用的损失函数。而且,随着误差的减小,梯度也在减小,这有利于收敛,即使使用固定的学习速率,也能较快的收敛到最小值。
缺点:当真实值y和预测值f(x)的差值大于1时,会放大误差;而当差值小于1时,则会缩小误差,这是平方运算决定的。MSE对于较大的误差(>1)给予较大的惩罚,较小的误差(<1)给予较小的惩罚。也就是说,对离群点比较敏感,受其影响较大。
# MSE
# 方法一:自定义函数
import numpy as np
def MSE(img1,img2):
mse = np.mean( (img1 - img2) ** 2 )
return mse
# 方法二:调用库函数
# 老版本的scikit-image,加载SSIM、PSNR、MSE的方式:
from skimage.measure import compare_mse as mse
# 新版本的scikit-image,加载方式:
from skimage.metrics import mean_squared_error as mse
PSNR(Peak Signal to Noise Ratio),峰值信噪比,是一种评价图像的客观标准。,应用场景有很多。它具有局性,PSNR是“Peak Signal to Noise Ratio”的缩写。peak的中文意思是顶点。而ratio的意思是比率或比列的。整个意思就是到达噪音比率的顶点信号,psnr一般是用于最大值信号和背景噪音之间的一个工程项目。通常在经过影像压缩之后,通常输出的影像都会在某种程度与原始影像不同。为了衡量经过处理后的影像品质,通常会参考PSNR值来衡量某个处理程序能否令人满意。它是原图像与被处理图 像之间的均方误差相对于(2n-1)2的对数值(信号最大值的平方,n是每个采样值的比特数),它的单位是dB。
PSNR是最普遍和使用最为广泛的一种图像客观评价指标,然而它是基于对应像素点间的误差,即 基于误差敏感的图像质量评价。由于并未考虑到人眼的视觉特性(人眼对空间频率较低的对比差异敏感度较高,人眼对亮度对比差异的敏感度较色度高,人眼对一个 区域的感知结果会受到其周围邻近区域的影响等),因而经常出现评价结果与人的主观感觉不一致的情况。
PSNR是通过MSE得出来的,公式如下:
其中,MAXI是表示图像点颜色的最大数值,如果每个采样点用 8 位表示,那么就是 255。
所以MSE越小,则PSNR越大;所以PSNR越大,代表着图像质量越好。一般来说,
# PSNR
# 方法一:自定义函数
import numpy
import math
def psnr(img1, img2):
mse = numpy.mean( (img1 - img2) ** 2 )
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
# 方法二:调用库函数
# 老版本的scikit-image,加载SSIM、PSNR、MSE的方式:
from skimage.measure import compare_ssim as ssim
from skimage.measure import compare_psnr as psnr
from skimage.measure import compare_mse as mse
# 新版本的scikit-image,加载方式:
from skimage.metrics import structural_similarity as ssim
from skimage.metrics import peak_signal_noise_ratio as psnr
from skimage.metrics import mean_squared_error as mse
SSIM(structural similarity),结构相似性,是一种衡量两幅图像相似度的指标。
SSIM算法主要用于检测两张相同尺寸的图像的相似度、或者检测图像的失真程度。
SSIM公式基于样本x和y之间的三个比较衡量:亮度 (luminance)、对比度 (contrast) 和结构 (structure)。
常数, , 是为了避免当分母为 0 时造成的不稳定问题。
为均值, 为方差, 表示协方差。
SSIM取值范围为[0,1],值越大表示输出图像和无失真图像的差距越小,即图像质量越好。
缺点:结构相似性指标有其限制,对于影像出现位移、缩放、旋转(皆属于非结构性的失真)的情况无法有效的运作。
# SSIM
# 方法一:自定义函数
# 很奇怪,计算出来和调用函数结果差异很大,建议直接调用函数
import numpy as np
def ssim(y_true , y_pred):
u_true = np.mean(y_true)
u_pred = np.mean(y_pred)
var_true = np.var(y_true)
var_pred = np.var(y_pred)
std_true = np.sqrt(var_true)
std_pred = np.sqrt(var_pred)
c1 = np.square(0.01*7)
c2 = np.square(0.03*7)
ssim = (2 * u_true * u_pred + c1) * (2 * std_pred * std_true + c2)
denom = (u_true ** 2 + u_pred ** 2 + c1) * (var_pred + var_true + c2)
return ssim / denom
# 方法二:调用库函数
# 老版本的scikit-image,加载SSIM、PSNR、MSE的方式:
from skimage.measure import compare_ssim as ssim
from skimage.measure import compare_psnr as psnr
from skimage.measure import compare_mse as mse
# 新版本的scikit-image,加载方式:
from skimage.metrics import structural_similarity as ssim
from skimage.metrics import peak_signal_noise_ratio as psnr
from skimage.metrics import mean_squared_error as mse
def structural_similarity(*, im1, im2,
win_size=None, gradient=False, data_range=None,
multichannel=False, gaussian_weights=False,
full=False, **kwargs)
上述原始计算方式仅法针对单通道灰度图,
求RGB图或多通道图时,PSNR有三种方式,其他类似:
分为多块时,在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性SSIM。
例:计算两个RGB图像的MSE(均方误差):
把图片表示成一个向量,通过计算向量之间的余弦距离来表征两张图片的相似度。
余弦相似度算法:一个向量空间中两个向量夹角间的余弦值作为衡量两个个体之间差异的大小,余弦值接近1,夹角趋于0,表明两个向量越相似,余弦值接近于0,夹角趋于90度,表明两个向量越不相似。
图片相似度计算方法总结 - 知乎 (zhihu.com)
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# 余弦相似度计算
from PIL import Image
from numpy import average, dot, linalg
# 对图片进行统一化处理
def get_thum(image, size=(64, 64), greyscale=False):
# 利用image对图像大小重新设置, Image.ANTIALIAS为高质量的
image = image.resize(size, Image.ANTIALIAS)
if greyscale:
# 将图片转换为L模式,其为灰度图,其每个像素用8个bit表示
image = image.convert('L')
return image
# 计算图片的余弦距离
def image_similarity_vectors_via_numpy(image1, image2):
image1 = get_thum(image1)
image2 = get_thum(image2)
images = [image1, image2]
vectors = []
norms = []
for image in images:
vector = []
for pixel_tuple in image.getdata():
vector.append(average(pixel_tuple))
vectors.append(vector)
# linalg=linear(线性)+algebra(代数),norm则表示范数
# 求图片的范数
norms.append(linalg.norm(vector, 2))
a, b = vectors
a_norm, b_norm = norms
# dot返回的是点积,对二维数组(矩阵)进行计算
res = dot(a / a_norm, b / b_norm)
return res
image1 = Image.open('010.jpg')
image2 = Image.open('011.jpg')
cosin = image_similarity_vectors_via_numpy(image1, image2)
print('图片余弦相似度', cosin)
图片相相似度计算(Hash、SSIM、compareHist)_南苏月的博客-CSDN博客_图像相似度计算公式
哈希算法-图片相似度计算_chenghaoy的博客-CSDN博客_均值哈希算法相似度
实现图片相似度比较的hash算法有三种:均值哈希算法(AHash),差值哈希算法(DHash),感知哈希算法 (PHash)。
哈希不是以严格的方式计算Hash值,而是以更加相对的方式计算哈希值,因为“相似”与否,就是一种相对的判定。值哈希算法、差值哈希算法和感知哈希算法都是值越小,相似度越高,取值为0-64,即汉明距离中,64位的hash值有多少不同。三直方图和单通道直方图的值为0-1,值越大,相似度越高。
一张图片就是一个二维信号,它包含了不同频率的成分。亮度变化小的区域是低频成分,它描述大范围的信息。而亮度变化剧烈的区域(比如物体的边缘)就是高频的成分,它描述具体的细节。或者说高频可以提供图片详细的信息,而低频可以提供一个框架。 而一张大的,详细的图片有很高的频率,而小图片缺乏图像细节,所以都是低频的。所以我们平时的下采样,也就是缩小图片的过程,实际上是损失高频信息的过程。均值哈希算法就是利用图片的低频信息。
具体步骤:
最后得到两张图片的指纹信息后,计算两组64位数据的汉明距离,即对比数据不同的位数,不同位数越少,表明图片的相似度越大。
分析: 均值哈希算法计算速度快,不受图片尺寸大小的影响,但是缺点就是对均值敏感,例如对图像进行伽马校正或直方图均衡就会影响均值,从而影响最终的hash值。
感知哈希算法是一个比均值哈希算法更为健壮的一种算法,与均值哈希算法的区别在于感知哈希算法是通过DCT(离散余弦变换)来获取图片的低频信息。
离散余弦变换(DCT)是种图像压缩算法,它将图像从像素域变换到频率域。然后一般图像都存在很多冗余和相关性的,所以转换到频率域之后,只有很少的一部分频率分量的系数才不为0,大部分系数都为0(或者说接近于0)。经过DCT变换后的系数矩阵从左上角到右下角频率越来越高,因此图片的能量主要保留在左上角的低频系数上了。
具体步骤:
分析: 结果并不能告诉我们真实性的低频率,只能粗略地告诉我们相对于平均值频率的相对比例。只要图片的整体结构保持不变,hash结果值就不变。能够避免伽马校正或颜色直方图被调整带来的影响。对于变形程度在25%以内的图片也能精准识别。
比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。
主要步骤:
import cv2
import numpy as np
#感知哈希算法
def pHash(image):
image = cv2.resize(image,(32,32), interpolation=cv2.INTER_CUBIC)
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# cv2.imshow('image', image)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 将灰度图转为浮点型,再进行dct变换
dct = cv2.dct(np.float32(image))
# print(dct)
# 取左上角的8*8,这些代表图片的最低频率
# 这个操作等价于c++中利用opencv实现的掩码操作
# 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分
dct_roi = dct[0:8,0:8]
avreage = np.mean(dct_roi)
hash = []
for i in range(dct_roi.shape[0]):
for j in range(dct_roi.shape[1]):
if dct_roi[i,j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash
#均值哈希算法
def aHash(image):
#缩放为8*8
image=cv2.resize(image,(8,8),interpolation=cv2.INTER_CUBIC)
#转换为灰度图
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
avreage = np.mean(image)
hash = []
for i in range(image.shape[0]):
for j in range(image.shape[1]):
if image[i,j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash
#差值感知算法
def dHash(image):
#缩放9*8
image=cv2.resize(image,(9,8),interpolation=cv2.INTER_CUBIC)
#转换灰度图
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# print(image.shape)
hash=[]
#每行前一个像素大于后一个像素为1,相反为0,生成哈希
for i in range(8):
for j in range(8):
if image[i,j]>image[i,j+1]:
hash.append(1)
else:
hash.append(0)
return hash
#计算汉明距离
def Hamming_distance(hash1,hash2):
num = 0
for index in range(len(hash1)):
if hash1[index] != hash2[index]:
num += 1
return num
if __name__ == "__main__":
image_file1 = './data/cartoon1.jpg'
image_file2 = './data/cartoon3.jpg'
img1 = cv2.imread(image_file1)
img2 = cv2.imread(image_file2)
hash1 = pHash(img1)
hash2 = pHash(img2)
dist = Hamming_distance(hash1, hash2)
#将距离转化为相似度
similarity = 1 - dist * 1.0 / 64
print(dist)
print(similarity)
图片的相似度--直方图距离 - 知乎 (zhihu.com)
方法描述:按照某种距离度量的标准对两幅图像的直方图进行相似度的测量。
图像直方图丰富的图像细节信息,反映了图像像素点的概率分布情况,统计每一个像素点强度值具有的像素个数。
计算步骤:
import cv2
def calculate(image1, image2):
# 灰度直方图算法
# 计算单通道的直方图的相似值
hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
# 计算直方图的重合度
degree = 0
for i in range(len(hist1)):
if hist1[i] != hist2[i]:
degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
else:
degree = degree + 1
degree = degree / len(hist1)
return degree
def classify_hist_with_split(image1, image2, size=(256, 256)):
# RGB每个通道的直方图相似度
# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
image1 = cv2.resize(image1, size)
image2 = cv2.resize(image2, size)
sub_image1 = cv2.split(image1)
sub_image2 = cv2.split(image2)
sub_data = 0
for im1, im2 in zip(sub_image1, sub_image2):
sub_data += calculate(im1, im2)
sub_data = sub_data / 3
return sub_data
归一化互信息(NMI)评价指标_易_的博客-CSDN博客_nmi指标
信息熵:对信息进行量化度量。可以理解为某种特定信息的出现概率。
相对熵:(relative entropy),又被称为Kullback-Leibler散度(Kullback-Leibler divergence,KL散度)或信息散度(information divergence),是两个概率分布(probability distribution)间差异的非对称性度量 。在在信息理论中,相对熵等价于两个概率分布的信息熵(Shannon entropy)的差值。
互信息:(Mutual Information)是信息论里一种有用的信息度量,它可以看成是一个随机变量中包含的关于另一个随机变量的信息量,或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性。
归一化互信息:将互信息放在[0,1]之间,容易评价算法的好坏。
from sklearn import metrics as mr
img1 = cv2.imread('1.png')
img2 = cv2.imread('2.png')
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])
nmi = mr.normalized_mutual_info_score(img1.reshape(-1), img2.reshape(-1))
GitHub - whtsky/pixelmatch-py: A fast pixel-level image comparison library, originally created to compare screenshots in tests.
利用像素之间的匹配来计算相似度
# https://github.com/whtsky/pixelmatch-py
# 第一步:
pip install pixelmatch
# 第二步:
from PIL import Image
from pixelmatch.contrib.PIL import pixelmatch
img_a = Image.open("a.png")
img_b = Image.open("b.png")
img_diff = Image.new("RGBA", img_a.size)
# note how there is no need to specify dimensions
mismatch = pixelmatch(img_a, img_b, img_diff, includeAA=True)
img_diff.save("diff.png")
有史以来最全的图像相似度算法_小殊小殊的博客-CSDN博客_图片相似度
使用四种方法计算图片相似度:MD5(粗暴的md5比较,判断是否完全相同)、直方图、PSNR、SSIM。
import numpy as np
from PIL import Image
from skimage.metrics import structural_similarity
import cv2
import os
import hashlib
import math
'''
粗暴的md5比较 返回是否完全相同
'''
def md5_similarity(img1_path, img2_path):
file1 = open(img1_path, "rb")
file2 = open(img2_path, "rb")
md = hashlib.md5()
md.update(file1.read())
res1 = md.hexdigest()
md = hashlib.md5()
md.update(file2.read())
res2 = md.hexdigest()
return res1 == res2
def normalize(data):
return data / np.sum(data)
'''
直方图相似度
相关性比较 cv2.HISTCMP_CORREL:值越大,相似度越高
相交性比较 cv2.HISTCMP_INTERSECT:值越大,相似度越高
卡方比较 cv2.HISTCMP_CHISQR:值越小,相似度越高
巴氏距离比较 cv2.HISTCMP_BHATTACHARYYA:值越小,相似度越高
'''
def hist_similarity(img1, img2, hist_size=256):
imghistb1 = cv2.calcHist([img1], [0], None, [hist_size], [0, 256])
imghistg1 = cv2.calcHist([img1], [1], None, [hist_size], [0, 256])
imghistr1 = cv2.calcHist([img1], [2], None, [hist_size], [0, 256])
imghistb2 = cv2.calcHist([img2], [0], None, [hist_size], [0, 256])
imghistg2 = cv2.calcHist([img2], [1], None, [hist_size], [0, 256])
imghistr2 = cv2.calcHist([img2], [2], None, [hist_size], [0, 256])
distanceb = cv2.compareHist(normalize(imghistb1), normalize(imghistb2), cv2.HISTCMP_CORREL)
distanceg = cv2.compareHist(normalize(imghistg1), normalize(imghistg2), cv2.HISTCMP_CORREL)
distancer = cv2.compareHist(normalize(imghistr1), normalize(imghistr2), cv2.HISTCMP_CORREL)
meandistance = np.mean([distanceb, distanceg, distancer])
return meandistance
def PSNR(img1, img2):
mse = np.mean((img1/255. - img2/255.) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 1
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
def SSIM(img1, img2):
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 计算两个灰度图像之间的结构相似度
score, diff = structural_similarity(gray1, gray2, win_size=101, full=True)
# diff = (diff * 255).astype("uint8")
# print("SSIM:{}".format(score))
return score, diff
def ssim(img1, img2):
u_true = np.mean(img1)
u_pred = np.mean(img2)
var_true = np.var(img1)
var_pred = np.var(img2)
std_true = np.sqrt(var_true)
std_pred = np.sqrt(var_pred)
c1 = np.square(0.01*7)
c2 = np.square(0.03*7)
ssim = (2 * u_true * u_pred + c1) * (2 * std_pred * std_true + c2)
denom = (u_true ** 2 + u_pred ** 2 + c1) * (var_pred + var_true + c2)
return ssim/denom
def MSE(img1,img2):
mse = np.mean( (img1 - img2) ** 2 )
return mse
if __name__ == '__main__':
img1_path = '1_08.jpg'
img2_path = '2_08.jpg'
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
# 1.粗暴的md5比较 返回是否完全相同
print('md5_similarity:', md5_similarity(img1_path, img2_path))
# 2.直方图相似度
print('hist_similarity:', hist_similarity(img1, img2))
# 3.PSNR
print('PSNR:', PSNR(img1, img2))
# 4.SSIM
print('灰度图SSIM:', SSIM(img1, img2)[0])
print('RGB图_ssim:', ssim(img1, img2))
print('RGB图_structural_similarity:', structural_similarity(img1,img2, multichannel=True))
# 5.MSE
print('MSE:', MSE(img1, img2))
效果展示:
两图md5_similarity: False
hist_similarity: 0.1344447074377748
PSNR: 12.980832701995697
灰度图SSIM: 0.5966066785284522
RGB图_ssim: 0.9917382398395064
RGB图_structural_similarity: 0.525279441002218
MSE: 86.05895699395074
import os
import numpy as np
from glob import glob
import cv2
from skimage.measure import compare_mse,compare_ssim,compare_psnr
def read_img(path):
return cv2.imread(path,cv2.IMREAD_GRAYSCALE)
def mse(tf_img1, tf_img2):
return compare_mse(tf_img1,tf_img2)
def psnr(tf_img1, tf_img2):
return compare_psnr(tf_img1,tf_img2)
def ssim(tf_img1, tf_img2):
return compare_ssim(tf_img1,tf_img2)
def main():
WSI_MASK_PATH1 = 'E:/test/A/'
WSI_MASK_PATH2 = 'E:/test/B/'
path_real = glob(os.path.join(WSI_MASK_PATH1, '*.jpg'))
path_fake = glob(os.path.join(WSI_MASK_PATH2, '*.jpg'))
list_psnr = []
list_ssim = []
list_mse = []
for i in range(len(path_real)):
t1 = read_img(path_real[i])
t2 = read_img(path_fake[i])
result1 = np.zeros(t1.shape,dtype=np.float32)
result2 = np.zeros(t2.shape,dtype=np.float32)
cv2.normalize(t1,result1,alpha=0,beta=1,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_32F)
cv2.normalize(t2,result2,alpha=0,beta=1,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_32F)
mse_num = mse(result1, result2)
psnr_num = psnr(result1, result2)
ssim_num = ssim(result1, result2)
list_psnr.append(psnr_num)
list_ssim.append(ssim_num)
list_mse.append(mse_num)
#输出每张图像的指标:
print("{}/".format(i+1)+"{}:".format(len(path_real)))
str = "\\"
print("image:"+path_real[i][(path_real[i].index(str)+1):])
print("PSNR:", psnr_num)
print("SSIM:", ssim_num)
print("MSE:",mse_num)
#输出平均指标:
print("平均PSNR:", np.mean(list_psnr)) # ,list_psnr)
print("平均SSIM:", np.mean(list_ssim)) # ,list_ssim)
print("平均MSE:", np.mean(list_mse)) # ,list_mse)
if __name__ == '__main__':
main()
Python计算Y通道或者RGB通道的PSNR_SSIM_未知量0520的博客-CSDN博客_folder_gt
'''
calculate the PSNR and SSIM.
same as MATLAB's results
https://blog.csdn.net/qq_45041702/article/details/120997743
'''
import os
import math
import numpy as np
import cv2
import glob
import os
def main():
# Configurations
# GT - Ground-truth;
# Gen: Generated / Restored / Recovered images
folder_GT = '/content/drive/MyDrive/Experiment/codes/26_PSNR_SSIM/All/groud_truth_png'
folder_Gen = '/content/drive/MyDrive/Experiment/codes/26_PSNR_SSIM/All/1_ESPCN_png'
#save the psnr and ssim score by txt
PS_path = '/content/drive/MyDrive/Experiment/codes/26_PSNR_SSIM/Score'
if not os.path.exists(PS_path):
print('NO_path to sava the NIQE_Score,Making....')
os.makedirs(PS_path)
else:
print("The NIQE_Score_path has existed")
PS_txt = open(PS_path +'/score1.txt', 'a' )
crop_border = 4 # same with scale
suffix = '' # suffix for Gen images
test_Y = False # True: test Y channel only; False: test RGB channels
PSNR_all = []
SSIM_all = []
img_list = sorted(glob.glob(folder_GT + '/*'))
if test_Y:
print('Testing Y channel.')
else:
print('Testing RGB channels.')
for i, img_path in enumerate(img_list):
base_name = os.path.splitext(os.path.basename(img_path))[0]
print(base_name)
im_GT = cv2.imread(img_path) / 255.
#不同格式图像
# im_Gen = cv2.imread(os.path.join(folder_Gen, base_name + suffix + '.tif')) / 255.
im_Gen = cv2.imread(os.path.join(folder_Gen, base_name + suffix + '.png')) / 255.
if test_Y and im_GT.shape[2] == 3: # evaluate on Y channel in YCbCr color space
im_GT_in = bgr2ycbcr(im_GT)
im_Gen_in = bgr2ycbcr(im_Gen)
else:
im_GT_in = im_GT
im_Gen_in = im_Gen
# crop borders
if crop_border == 0:
cropped_GT = im_GT_in
cropped_Gen = im_Gen_in
else:
if im_GT_in.ndim == 3:
cropped_GT = im_GT_in[crop_border:-crop_border, crop_border:-crop_border, :]
cropped_Gen = im_Gen_in[crop_border:-crop_border, crop_border:-crop_border, :]
elif im_GT_in.ndim == 2:
cropped_GT = im_GT_in[crop_border:-crop_border, crop_border:-crop_border]
cropped_Gen = im_Gen_in[crop_border:-crop_border, crop_border:-crop_border]
else:
raise ValueError('Wrong image dimension: {}. Should be 2 or 3.'.format(im_GT_in.ndim))
#不同通道数(Y通道和RGB三个通道),需要更改
# calculate PSNR and SSIM
# PSNR = calculate_psnr(cropped_GT * 255, cropped_Gen * 255)
PSNR = calculate_rgb_psnr(cropped_GT * 255, cropped_Gen * 255)
SSIM = calculate_ssim(cropped_GT * 255, cropped_Gen * 255)
print('{:3d} - {:25}. \tPSNR: {:.4f} dB, \tSSIM: {:.4f}'.format(
i + 1, base_name, PSNR, SSIM))
PSNR_all.append(PSNR)
SSIM_all.append(SSIM)
single_info = '[{}],PSNR(dB),{:.4f}, SSIM,{:.4f}'
PS_txt.write(single_info.format(base_name,PSNR,SSIM))
PS_txt.write("\n")
Mean_format = 'Mean_PSNR: {:.4f}, Mean_SSIM: {:.4f}'
Mean_PSNR = sum(PSNR_all) / len(PSNR_all)
Mean_SSIM = sum(SSIM_all) / len(SSIM_all)
print(Mean_format.format(Mean_PSNR,Mean_SSIM))
PS_txt.write(Mean_format.format(Mean_PSNR,Mean_SSIM))
PS_txt.write('\n')
def calculate_psnr(img1, img2):
# img1 and img2 have range [0, 255]
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
mse = np.mean((img1 - img2)**2)
if mse == 0:
return float('inf')
return 20 * math.log10(255.0 / math.sqrt(mse))
def calculate_rgb_psnr(img1, img2):
"""calculate psnr among rgb channel, img1 and img2 have range [0, 255]
"""
n_channels = np.ndim(img1)
sum_psnr = 0
for i in range(n_channels):
this_psnr = calculate_psnr(img1[:,:,i], img2[:,:,i])
sum_psnr += this_psnr
return sum_psnr/n_channels
def ssim(img1, img2):
C1 = (0.01 * 255)**2
C2 = (0.03 * 255)**2
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
kernel = cv2.getGaussianKernel(11, 1.5)
window = np.outer(kernel, kernel.transpose())
mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5] # valid
mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
mu1_sq = mu1**2
mu2_sq = mu2**2
mu1_mu2 = mu1 * mu2
sigma1_sq = cv2.filter2D(img1**2, -1, window)[5:-5, 5:-5] - mu1_sq
sigma2_sq = cv2.filter2D(img2**2, -1, window)[5:-5, 5:-5] - mu2_sq
sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
(sigma1_sq + sigma2_sq + C2))
return ssim_map.mean()
def calculate_ssim(img1, img2):
'''calculate SSIM
the same outputs as MATLAB's
img1, img2: [0, 255]
'''
if not img1.shape == img2.shape:
raise ValueError('Input images must have the same dimensions.')
if img1.ndim == 2:
return ssim(img1, img2)
elif img1.ndim == 3:
if img1.shape[2] == 3:
ssims = []
for i in range(img1.shape[2]):
ssims.append(ssim(img1[..., i], img2[..., i]))
return np.array(ssims).mean()
elif img1.shape[2] == 1:
return ssim(np.squeeze(img1), np.squeeze(img2))
else:
raise ValueError('Wrong input image dimensions.')
def bgr2ycbcr(img, only_y=True):
'''same as matlab rgb2ycbcr
only_y: only return Y channel
Input:
uint8, [0, 255]
float, [0, 1]
'''
in_img_type = img.dtype
img.astype(np.float32)
if in_img_type != np.uint8:
img *= 255.
# convert
if only_y:
rlt = np.dot(img, [24.966, 128.553, 65.481]) / 255.0 + 16.0
else:
rlt = np.matmul(img, [[24.966, 112.0, -18.214], [128.553, -74.203, -93.786],
[65.481, -37.797, 112.0]]) / 255.0 + [16, 128, 128]
if in_img_type == np.uint8:
rlt = rlt.round()
else:
rlt /= 255.
return rlt.astype(in_img_type)
if __name__ == '__main__':
main()
结果展示:
SSIM---结构相似性算法(OpenCV+Python)_hedgehog__的博客-CSDN博客_python 结构相似性 通过调用skimage.metrics包下的SSIM算法,结合OpenCV的阈值分割及轮廓提取算法,找出两幅图像的差异。
# https://blog.csdn.net/hedgehog__/article/details/107257755
import cv2
import imutils
from skimage.metrics import structural_similarity
import time
from skimage import filters, img_as_ubyte
import numpy as np
start = time.time()
# 读入图像,转为灰度图像
src = cv2.imread('C:/Users/Hedgehog/Desktop/right.jpg')
img = cv2.imread('C:/Users/Hedgehog/Desktop/left.jpg')
grayA = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 计算两个灰度图像之间的结构相似度
(score, diff) = structural_similarity(grayA, grayB, win_size=101, full=True)
diff = (diff * 255).astype("uint8")
cv2.namedWindow("diff", cv2.WINDOW_NORMAL)
cv2.imshow("diff", diff)
print("SSIM:{}".format(score))
# 找到不同的轮廓以致于可以在表示为 '不同'的区域放置矩形
# 全局自适应阈值分割(二值化),返回值有两个,第一个是阈值,第二个是二值图像
dst = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cv2.namedWindow("threshold", cv2.WINDOW_NORMAL)
cv2.imshow('threshold', dst)
# findContours找轮廓,返回值有两个,第一个是轮廓信息,第二个是轮廓的层次信息(“树”状拓扑结构)
# cv2.RETR_EXTERNAL:只检测最外层轮廓
# cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向和对角线方向的元素,保留该方向的终点坐标,如矩形的轮廓可用4个角点表示
contours, hierarchy = cv2.findContours(dst.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(contours)
newimg = np.zeros(dst.shape, np.uint8) # 定义一个和图像分割处理后相同大小的黑色图
# drawContours画轮廓,将找到的轮廓信息画出来
cv2.drawContours(newimg, contours, -1, (255, 255, 255), 1)
cv2.namedWindow("contours", cv2.WINDOW_NORMAL)
cv2.imshow('contours', newimg)
# cnts = cnts[0] if imutils.is_cv3() else cnts[0] 取findContours函数的第一个返回值,即取轮廓信息
# 找到一系列区域,在区域周围放置矩形
for c in contours:
(x, y, w, h) = cv2.boundingRect(c) # boundingRect函数:计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的
cv2.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2) # rectangle函数:使用对角线的两点pt1,pt2画一个矩形轮廓
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 画矩形的图, pt1, pt2,(对角线两点的坐标), 矩形边框的颜色,矩形边框的粗细
end = time.time()
print(end - start)
# 用cv2.imshow 展现最终对比之后的图片
cv2.namedWindow("right", cv2.WINDOW_NORMAL)
cv2.imshow('right', src)
cv2.namedWindow("left", cv2.WINDOW_NORMAL)
cv2.imshow('left', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果展示:
计算两幅图像的相似度总结_JerrySing的博客-CSDN博客_compare_ssim
Python计算图片之间的相似度_~小疯子~的博客-CSDN博客_python 识别图片相似度
有史以来最全的图像相似度算法_小殊小殊的博客-CSDN博客_图片相似度
(超详细)实现计算图片相似度MSE和PSNR_Natuki丶的博客-CSDN博客_计算psnr和mse
Python批量计算PSNR、SSIM、MSE_杨杨杨Garrick的博客-CSDN博客
图像质量评价指标MSE/PSNR/SSIM_秋天的从从的博客-CSDN博客_图像mse
图片相相似度计算(Hash、SSIM、compareHist)_南苏月的博客-CSDN博客_图像相似度计算公式
【OpenCV-Python】:图像PSNR、SSIM、MSE计算_米开朗琪罗~的博客-CSDN博客_图像的mse计算
Python计算Y通道或者RGB通道的PSNR_SSIM_未知量0520的博客-CSDN博客_folder_gt
scikit-image 0.18.0版本计算PSNR、SSIM、MSE(Python代码)_YZBshanshan的博客-CSDN博客_scikit-image版本
图像质量评估中的PSNR和SSIM的定义,公式和含义_·如烟·的博客-CSDN博客_psnr定义
【基础知识】图像去噪评估—PSNR和SSIM - 梁君牧 - 博客园 (cnblogs.com)
SSIM---结构相似性算法(OpenCV+Python)_hedgehog__的博客-CSDN博客_python 结构相似性
图片相似度计算方法总结 - 知乎 (zhihu.com)
相似度计算方法(三) 余弦相似度_潘永青的博客-CSDN博客_余弦相似度
图片的相似度--直方图距离 - 知乎 (zhihu.com)