红外与可见光图像融合评价指标(cddfusion中的代码Evaluator.py)

一、Evaluator.py全部代码(可正常调用)


import numpy as np
import cv2
import sklearn.metrics as skm
from scipy.signal import convolve2d
import math
from skimage.metrics import structural_similarity as ssimdef image_read_cv2(path, mode='RGB'):img_BGR = cv2.imread(path).astype('float32')assert mode == 'RGB' or mode == 'GRAY' or mode == 'YCrCb', 'mode error'if mode == 'RGB':img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)elif mode == 'GRAY':  img = np.round(cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY))elif mode == 'YCrCb':img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)return imgclass Evaluator():@classmethoddef input_check(cls, imgF, imgA=None, imgB=None): if imgA is None:assert type(imgF) == np.ndarray, 'type error'assert len(imgF.shape) == 2, 'dimension error'else:assert type(imgF) == type(imgA) == type(imgB) == np.ndarray, 'type error'assert imgF.shape == imgA.shape == imgB.shape, 'shape error'assert len(imgF.shape) == 2, 'dimension error'@classmethoddef EN(cls, img):  # entropycls.input_check(img)a = np.uint8(np.round(img)).flatten()h = np.bincount(a) / a.shape[0]return -sum(h * np.log2(h + (h == 0)))@classmethoddef SD(cls, img):cls.input_check(img)return np.std(img)@classmethoddef SF(cls, img):cls.input_check(img)return np.sqrt(np.mean((img[:, 1:] - img[:, :-1]) ** 2) + np.mean((img[1:, :] - img[:-1, :]) ** 2))@classmethoddef AG(cls, img):  # Average gradientcls.input_check(img)Gx, Gy = np.zeros_like(img), np.zeros_like(img)Gx[:, 0] = img[:, 1] - img[:, 0]Gx[:, -1] = img[:, -1] - img[:, -2]Gx[:, 1:-1] = (img[:, 2:] - img[:, :-2]) / 2Gy[0, :] = img[1, :] - img[0, :]Gy[-1, :] = img[-1, :] - img[-2, :]Gy[1:-1, :] = (img[2:, :] - img[:-2, :]) / 2return np.mean(np.sqrt((Gx ** 2 + Gy ** 2) / 2))@classmethoddef MI(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return skm.mutual_info_score(image_F.flatten(), image_A.flatten()) + skm.mutual_info_score(image_F.flatten(),image_B.flatten())@classmethoddef MSE(cls, image_F, image_A, image_B):  # MSEcls.input_check(image_F, image_A, image_B)return (np.mean((image_A - image_F) ** 2) + np.mean((image_B - image_F) ** 2)) / 2@classmethoddef CC(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)rAF = np.sum((image_A - np.mean(image_A)) * (image_F - np.mean(image_F))) / np.sqrt((np.sum((image_A - np.mean(image_A)) ** 2)) * (np.sum((image_F - np.mean(image_F)) ** 2)))rBF = np.sum((image_B - np.mean(image_B)) * (image_F - np.mean(image_F))) / np.sqrt((np.sum((image_B - np.mean(image_B)) ** 2)) * (np.sum((image_F - np.mean(image_F)) ** 2)))return (rAF + rBF) / 2@classmethoddef PSNR(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return 10 * np.log10(np.max(image_F) ** 2 / cls.MSE(image_F, image_A, image_B))@classmethoddef SCD(cls, image_F, image_A, image_B): # The sum of the correlations of differencescls.input_check(image_F, image_A, image_B)imgF_A = image_F - image_AimgF_B = image_F - image_Bcorr1 = np.sum((image_A - np.mean(image_A)) * (imgF_B - np.mean(imgF_B))) / np.sqrt((np.sum((image_A - np.mean(image_A)) ** 2)) * (np.sum((imgF_B - np.mean(imgF_B)) ** 2)))corr2 = np.sum((image_B - np.mean(image_B)) * (imgF_A - np.mean(imgF_A))) / np.sqrt((np.sum((image_B - np.mean(image_B)) ** 2)) * (np.sum((imgF_A - np.mean(imgF_A)) ** 2)))return corr1 + corr2@classmethoddef VIFF(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return cls.compare_viff(image_A, image_F)+cls.compare_viff(image_B, image_F)@classmethoddef compare_viff(cls,ref, dist): # viff of a pair of picturessigma_nsq = 2eps = 1e-10num = 0.0den = 0.0for scale in range(1, 5):N = 2 ** (4 - scale + 1) + 1sd = N / 5.0# Create a Gaussian kernel as MATLAB'sm, n = [(ss - 1.) / 2. for ss in (N, N)]y, x = np.ogrid[-m:m + 1, -n:n + 1]h = np.exp(-(x * x + y * y) / (2. * sd * sd))h[h < np.finfo(h.dtype).eps * h.max()] = 0sumh = h.sum()if sumh != 0:win = h / sumhif scale > 1:ref = convolve2d(ref, np.rot90(win, 2), mode='valid')dist = convolve2d(dist, np.rot90(win, 2), mode='valid')ref = ref[::2, ::2]dist = dist[::2, ::2]mu1 = convolve2d(ref, np.rot90(win, 2), mode='valid')mu2 = convolve2d(dist, np.rot90(win, 2), mode='valid')mu1_sq = mu1 * mu1mu2_sq = mu2 * mu2mu1_mu2 = mu1 * mu2sigma1_sq = convolve2d(ref * ref, np.rot90(win, 2), mode='valid') - mu1_sqsigma2_sq = convolve2d(dist * dist, np.rot90(win, 2), mode='valid') - mu2_sqsigma12 = convolve2d(ref * dist, np.rot90(win, 2), mode='valid') - mu1_mu2sigma1_sq[sigma1_sq < 0] = 0sigma2_sq[sigma2_sq < 0] = 0g = sigma12 / (sigma1_sq + eps)sv_sq = sigma2_sq - g * sigma12g[sigma1_sq < eps] = 0sv_sq[sigma1_sq < eps] = sigma2_sq[sigma1_sq < eps]sigma1_sq[sigma1_sq < eps] = 0g[sigma2_sq < eps] = 0sv_sq[sigma2_sq < eps] = 0sv_sq[g < 0] = sigma2_sq[g < 0]g[g < 0] = 0sv_sq[sv_sq <= eps] = epsnum += np.sum(np.log10(1 + g * g * sigma1_sq / (sv_sq + sigma_nsq)))den += np.sum(np.log10(1 + sigma1_sq / sigma_nsq))vifp = num / denif np.isnan(vifp):return 1.0else:return vifp@classmethoddef Qabf(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)gA, aA = cls.Qabf_getArray(image_A)gB, aB = cls.Qabf_getArray(image_B)gF, aF = cls.Qabf_getArray(image_F)QAF = cls.Qabf_getQabf(aA, gA, aF, gF)QBF = cls.Qabf_getQabf(aB, gB, aF, gF)# 计算QABFdeno = np.sum(gA + gB)nume = np.sum(np.multiply(QAF, gA) + np.multiply(QBF, gB))return nume / deno@classmethoddef Qabf_getArray(cls,img):# Sobel Operator Sobelh1 = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]).astype(np.float32)h2 = np.array([[0, 1, 2], [-1, 0, 1], [-2, -1, 0]]).astype(np.float32)h3 = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]).astype(np.float32)SAx = convolve2d(img, h3, mode='same')SAy = convolve2d(img, h1, mode='same')gA = np.sqrt(np.multiply(SAx, SAx) + np.multiply(SAy, SAy))aA = np.zeros_like(img)aA[SAx == 0] = math.pi / 2aA[SAx != 0]=np.arctan(SAy[SAx != 0] / SAx[SAx != 0])return gA, aA@classmethoddef Qabf_getQabf(cls,aA, gA, aF, gF):L = 1Tg = 0.9994kg = -15Dg = 0.5Ta = 0.9879ka = -22Da = 0.8GAF,AAF,QgAF,QaAF,QAF = np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA)GAF[gA>gF]=gF[gA>gF]/gA[gA>gF]GAF[gA == gF] = gF[gA == gF]GAF[gA <gF] = gA[gA<gF]/gF[gA<gF]AAF = 1 - np.abs(aA - aF) / (math.pi / 2)QgAF = Tg / (1 + np.exp(kg * (GAF - Dg)))QaAF = Ta / (1 + np.exp(ka * (AAF - Da)))QAF = QgAF* QaAFreturn QAF# @classmethod# def SSIM(cls, image_F, image_A, image_B):#     cls.input_check(image_F, image_A, image_B)#     return ssim(image_F,image_A)+ssim(image_F,image_B)@classmethoddef SSIM(cls,image_F, image_A, image_B):# 假设图像已经归一化并且在 [0, 1] 范围内data_range = 1.0  # 如果您的图像有不同的范围,请更新这个值cls.input_check(image_F, image_A, image_B)# 计算 image_F 和 image_A,以及 image_F 和 image_B 之间的 SSIMssim_score_A = ssim(image_F, image_A, data_range=data_range)ssim_score_B = ssim(image_F, image_B, data_range=data_range)# 返回 SSIM 的平均值return (ssim_score_A + ssim_score_B) / 2def VIFF(image_F, image_A, image_B):refA=image_ArefB=image_Bdist=image_Fsigma_nsq = 2eps = 1e-10numA = 0.0denA = 0.0numB = 0.0denB = 0.0for scale in range(1, 5):N = 2 ** (4 - scale + 1) + 1sd = N / 5.0# Create a Gaussian kernel as MATLAB'sm, n = [(ss - 1.) / 2. for ss in (N, N)]y, x = np.ogrid[-m:m + 1, -n:n + 1]h = np.exp(-(x * x + y * y) / (2. * sd * sd))h[h < np.finfo(h.dtype).eps * h.max()] = 0sumh = h.sum()if sumh != 0:win = h / sumhif scale > 1:refA = convolve2d(refA, np.rot90(win, 2), mode='valid')refB = convolve2d(refB, np.rot90(win, 2), mode='valid')dist = convolve2d(dist, np.rot90(win, 2), mode='valid')refA = refA[::2, ::2]refB = refB[::2, ::2]dist = dist[::2, ::2]mu1A = convolve2d(refA, np.rot90(win, 2), mode='valid')mu1B = convolve2d(refB, np.rot90(win, 2), mode='valid')mu2 = convolve2d(dist, np.rot90(win, 2), mode='valid')mu1_sq_A = mu1A * mu1Amu1_sq_B = mu1B * mu1Bmu2_sq = mu2 * mu2mu1A_mu2 = mu1A * mu2mu1B_mu2 = mu1B * mu2sigma1A_sq = convolve2d(refA * refA, np.rot90(win, 2), mode='valid') - mu1_sq_Asigma1B_sq = convolve2d(refB * refB, np.rot90(win, 2), mode='valid') - mu1_sq_Bsigma2_sq = convolve2d(dist * dist, np.rot90(win, 2), mode='valid') - mu2_sqsigma12_A = convolve2d(refA * dist, np.rot90(win, 2), mode='valid') - mu1A_mu2sigma12_B = convolve2d(refB * dist, np.rot90(win, 2), mode='valid') - mu1B_mu2sigma1A_sq[sigma1A_sq < 0] = 0sigma1B_sq[sigma1B_sq < 0] = 0sigma2_sq[sigma2_sq < 0] = 0gA = sigma12_A / (sigma1A_sq + eps)gB = sigma12_B / (sigma1B_sq + eps)sv_sq_A = sigma2_sq - gA * sigma12_Asv_sq_B = sigma2_sq - gB * sigma12_BgA[sigma1A_sq < eps] = 0gB[sigma1B_sq < eps] = 0sv_sq_A[sigma1A_sq < eps] = sigma2_sq[sigma1A_sq < eps]sv_sq_B[sigma1B_sq < eps] = sigma2_sq[sigma1B_sq < eps]sigma1A_sq[sigma1A_sq < eps] = 0sigma1B_sq[sigma1B_sq < eps] = 0gA[sigma2_sq < eps] = 0gB[sigma2_sq < eps] = 0sv_sq_A[sigma2_sq < eps] = 0sv_sq_B[sigma2_sq < eps] = 0sv_sq_A[gA < 0] = sigma2_sq[gA < 0]sv_sq_B[gB < 0] = sigma2_sq[gB < 0]gA[gA < 0] = 0gB[gB < 0] = 0sv_sq_A[sv_sq_A <= eps] = epssv_sq_B[sv_sq_B <= eps] = epsnumA += np.sum(np.log10(1 + gA * gA * sigma1A_sq / (sv_sq_A + sigma_nsq)))numB += np.sum(np.log10(1 + gB * gB * sigma1B_sq / (sv_sq_B + sigma_nsq)))denA += np.sum(np.log10(1 + sigma1A_sq / sigma_nsq))denB += np.sum(np.log10(1 + sigma1B_sq / sigma_nsq))vifpA = numA / denAvifpB =numB / denBif np.isnan(vifpA):vifpA=1if np.isnan(vifpB):vifpB = 1return vifpA+vifpB

1.图像读取函数image_read_cv2(): 

函数image_read_cv2(): 

def image_read_cv2(path, mode='RGB'):img_BGR = cv2.imread(path).astype('float32')assert mode == 'RGB' or mode == 'GRAY' or mode == 'YCrCb', 'mode error'if mode == 'RGB':img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)elif mode == 'GRAY':  img = np.round(cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY))elif mode == 'YCrCb':img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)return img

将读入的图像全部转化为单通道的灰度图像。

2.输入图像格式检查函数input_check(): 

函数input_check():

@classmethoddef input_check(cls, imgF, imgA=None, imgB=None): if imgA is None:assert type(imgF) == np.ndarray, 'type error'assert len(imgF.shape) == 2, 'dimension error'else:assert type(imgF) == type(imgA) == type(imgB) == np.ndarray, 'type error'assert imgF.shape == imgA.shape == imgB.shape, 'shape error'assert len(imgF.shape) == 2, 'dimension error'

定义了一个类方法(classmethod)input_check,也就是说在类的其他方法中可以通过cls.input_check()直接调用这个方法。该函数主要的作用是检查输入图像的格式。

如果imgANone

  • 确保imgF的类型是numpy.ndarray(NumPy数组),如果不是,抛出一个类型错误的异常。
  • 确认imgF的维度是2(二维数组),如果不是,抛出一个维度错误的异常。

如果imgA不为None

  • 确保imgFimgAimgB的类型都是numpy.ndarray,如果不是,抛出一个类型错误的异常。
  • 确保imgFimgAimgB的形状相同,如果不是,抛出一个形状错误的异常。
  • 再次确认imgF的维度是2。

二、图像评价指标(12种)

1. EN(信息熵 Entropy)

信息熵主要是度量图像包含信息量多少的一个客观评价指标,a表示灰度值,P(a)表示灰度概率分布:

信息熵越高表示融合图像的信息量越丰富,质量越好。

代码如下:(只检查融合图像)
def EN(cls, img):  # entropycls.input_check(img)a = np.uint8(np.round(img)).flatten()h = np.bincount(a) / a.shape[0]return -sum(h * np.log2(h + (h == 0)))

a = np.uint8(np.round(img)).flatten(): np.round():对括号中的内容进行四舍五入的操作。不会改变原数组,而是返回一个新的数组,除非你明确地将结果赋值给原数组的一个元素。然后将新的数组转换为整数(np.uint8 表示无符号8位整数)。最后使用.flatten将其展平为一维数组。

h = np.bincount(a) / a.shape[0]: 使用 np.bincount 函数计算数组 a 中每个整数值出现的次数,并除以总像素数 a.shape[0],得到每个整数值的概率分布 h

return -sum(h * np.log2(h + (h == 0))): 最后,函数计算熵。根据信息论,熵(H)定义为每个可能状态(这里对应每个整数值)的概率(h)乘以以自然对数为底的负对数(-np.log2),然后求和。+ (h == 0) 是为了避免对0取对数,因为自然对数的底数不能为0,所以这里用一个小技巧处理概率为0的情况。

2. SD(标准差 standard Deviation)

是一种衡量数据集中数据分布或离散程度的统计量。在图像处理中,标准差通常用来评价图像的对比度和清晰度,因此也可以用来评价融合图像的质量。

  1. 对比度评价:标准差反映了图像像素值的变化范围,对比度高的图像通常具有较大的标准差。因此,通过比较融合图像和原始图像的标准差,可以评价融合后图像的对比度是否有所提高或降低。

  2. 清晰度评价:清晰的图像通常具有较高的对比度,因此标准差也可以间接反映图像的清晰度。融合图像的标准差较高可能表示图像边缘清晰,细节丰富。

所以融合图像的SD越大越好吗?(NO)

并不是,

具体来说,SD的大小与融合图像的对比度、清晰度和一致性程度存在一定的关联,但并不是越大越好。

  1. 对比度: SD的大小与融合图像的对比度有一定的正相关关系,即SD越大,对比度可能也会越高。但是,过高的对比度可能导致图像过亮或过暗,影响观察体验。因此,在融合图像时需要根据具体应用场景来寻找适合的对比度。

  2. 清晰度: SD的大小与融合图像的清晰度也有一定的正相关关系,即SD越大,图像细节可能也会更加清晰。但是,过高的SD可能导致图像出现过多噪声或失真,影响观察体验。因此,在融合图像时需要根据具体应用场景来寻找适合的清晰度。

  3. 一致性: SD的大小与融合图像的一致性程度没有明确的相关关系,因此SD的大小并不能直接反映融合图像的一致性。

综上所述,SD的大小并不是融合图像的绝对评价指标,而是需要根据具体应用场景和其他图像质量评价指标来进行综合评价。在某些情况下,SD的大小可能会提示融合图像的质量有所提高,但是过高的SD也可能导致图像质量下降。因此,在融合图像时需要谨慎地考虑SD的大小,并结合其他指标进行综合评价。

代码如下:(只检查融合图像)
 def SD(cls, img):cls.input_check(img)return np.std(img)

3.  SF(空间频率 Spatial Frequency)

空间频率(Spatial Frequency)反映图像灰度的变化率,空间频率越大表示图像越清晰,融合图像质量越好。其计算公式如下:

 

代码如下:(只检查融合图像)
 def SF(cls, img):cls.input_check(img)return np.sqrt(np.mean((img[:, 1:] - img[:, :-1]) ** 2) + np.mean((img[1:, :] - img[:-1, :]) ** 2))

4.  AG(平均梯度 Average Gradient )

平均梯度(Average Gradient)可以用于衡量融合图像的清晰程度,可以认为平均梯度越大,图像清晰度越好,融合质量越好。计算公式如下:

其中H表示融合图像,M与N分别表示图像的高和宽。

 def AG(cls, img):  # Average gradientcls.input_check(img)Gx, Gy = np.zeros_like(img), np.zeros_like(img)Gx[:, 0] = img[:, 1] - img[:, 0]Gx[:, -1] = img[:, -1] - img[:, -2]Gx[:, 1:-1] = (img[:, 2:] - img[:, :-2]) / 2Gy[0, :] = img[1, :] - img[0, :]Gy[-1, :] = img[-1, :] - img[-2, :]Gy[1:-1, :] = (img[2:, :] - img[:-2, :]) / 2return np.mean(np.sqrt((Gx ** 2 + Gy ** 2) / 2))

5.MI(互信息 Mutual Information)

可度量两幅图像之间的相似程度,即融合图像获取了原图像信息量的多少。互信息越大,表示融合图像保留更多源图像信息,质量越好。互信息是根据图像的信息熵H(A)和联合信息熵H(A,B):

代码如下:(计算三幅图片的)
def MI(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return skm.mutual_info_score(image_F.flatten(), image_A.flatten()) + skm.mutual_info_score(image_F.flatten(),image_B.flatten())

使用了 skm.mutual_info_score 函数来计算互信息,这个函数来自于 sklearn.metrics 模块,用于评估两个离散或连续随机变量之间的互信息。 

最后的结果是融合图像和可见光图像的互信息加上融合图像和红外图像的互信息。

6.MSE(均方误差 Mean Square Error)

反映的是变量间的差异程度,是一种基于像素误差的图像质量客观评价指标,用于衡量融合图像和理想参考图像之间的差异,MSE越小,表示融合图像质量越好。
均方根误差(Root Mean Square Error)是一个翻译空间细节信息的评价指标,公式如下:

归一化均方根误差(normalized root mean square error)就是将RMSE的值变成(0,1)之间。

代码如下:(越小越好,输入三幅图片)
 def MSE(cls, image_F, image_A, image_B):  # MSEcls.input_check(image_F, image_A, image_B)return (np.mean((image_A - image_F) ** 2) + np.mean((image_B - image_F) ** 2)) / 2

计算了图像 image_A 与图像 image_F 之间的均方误差,以及图像 image_B 与图像 image_F 之间的均方误差,然后将这两个均方误差值相加并除以2取平均,最终返回这个平均值作为结果。这里使用了 np.mean 函数来计算均值,** 表示乘方操作,即计算差的平方。均方误差用于评估两幅图像之间的差异程度,值越小表示两幅图像越相似。 

7.CC(相关系数  Correlation Coefficient)

CC 是一种用于衡量图像之间相关性的指标,通常用于评估图像的相似性或质量。

相关系数用于衡量两个变量之间的线性关系强度,取值范围为[-1, 1],值为1表示完全正相关,值为-1表示完全负相关,值为0表示无相关性。

代码如下:(越接近1越好,输入三幅图片)
  def CC(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)rAF = np.sum((image_A - np.mean(image_A)) * (image_F - np.mean(image_F))) / np.sqrt((np.sum((image_A - np.mean(image_A)) ** 2)) * (np.sum((image_F - np.mean(image_F)) ** 2)))rBF = np.sum((image_B - np.mean(image_B)) * (image_F - np.mean(image_F))) / np.sqrt((np.sum((image_B - np.mean(image_B)) ** 2)) * (np.sum((image_F - np.mean(image_F)) ** 2)))return (rAF + rBF) / 2

计算了图像 image_A 与图像 image_F 之间的相关系数 rAF。相关系数用于衡量两个变量之间的线性关系强度,取值范围为[-1, 1],值为1表示完全正相关,值为-1表示完全负相关,值为0表示无相关性。这里使用了 np.sum 函数来计算总和,np.mean 函数来计算均值,** 表示乘方操作。

计算了图像 image_B 与图像 image_F 之间的相关系数 rBF,同样使用了类似的计算方法。

最后返回了图像 image_A 与图像 image_F 之间的相关系数 rAF 和图像 image_B 与图像 image_F 之间的相关系数 rBF 的平均值作为最终结果。这里假设两个相关系数具有相同的权重,因此取平均值。

8.PSNR(峰值信噪比  Peak signal to noise ration)

用于衡量图像有效信息与噪声之间的比率,能够反映图像是否失真。

Z表示理想参考图像灰度最大值与最小值之差,通常为255。PSNR的值越大,表示融合图像的质量越好。

代码如下:(越大越好,输入三幅图片)
def PSNR(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return 10 * np.log10(np.max(image_F) ** 2 / cls.MSE(image_F, image_A, image_B))

直接用img_F的z的平方除以之前就算好的MSE。

9.SCD(差异相关和  Sum of the Correlations of Differences)

代码如下:((-1,1)表示相关性,所以最好是正相关,也就是接近1)
    @classmethoddef corr2(a, b):a = a - np.mean(a)b = b - np.mean(b)r = np.sum(a * b) / np.sqrt(np.sum(a * a) * np.sum(b * b))return r@classmethoddef SCD(cls, image_F, image_A, image_B): # The sum of the correlations of differencescls.input_check(image_F, image_A, image_B)r = cls.corr2(image_F - image_B, image_A) + cls.corr2(image_F - image_A, image_B)return r

这段代码中的SCD方法计算了两幅原始图像image_Aimage_B分别与融合后的图像image_F的差值图像之间的相关性之和。具体来说,它首先调用corr2方法计算了image_F - image_Bimage_A之间的相关性,然后计算了image_F - image_Aimage_B之间的相关性,最后将这两个相关性值相加得到最终的SCD值。

在图像融合领域中,SCD值可以用来评估融合后的图像与原始图像之间的结构相似性,即差异相关和。通过计算差值图像之间的相关性,可以评估融合后图像的质量,以及融合过程中保留了多少原始图像的结构信息。

因此,这段代码中的SCD方法实际上是在计算图像融合质量的一个指标,通过分析差值图像之间的相关性来评估融合效果。

10.VIFF(视觉保真度 The visual information fidelity for fusion)

是基于视觉信息保真度提出的衡量融合图像质量的指标,由于太复杂了,详见A new image fusion performance metric based on visual information fidelity。VIFF的值越大,表示融合图像质量越好。

代码如下:(越接近1越好,输入三张图片)
@classmethoddef VIFF(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return cls.compare_viff(image_A, image_F)+cls.compare_viff(image_B, image_F)@classmethoddef compare_viff(cls,ref, dist): # viff of a pair of picturessigma_nsq = 2eps = 1e-10num = 0.0den = 0.0for scale in range(1, 5):N = 2 ** (4 - scale + 1) + 1sd = N / 5.0# Create a Gaussian kernel as MATLAB'sm, n = [(ss - 1.) / 2. for ss in (N, N)]y, x = np.ogrid[-m:m + 1, -n:n + 1]h = np.exp(-(x * x + y * y) / (2. * sd * sd))h[h < np.finfo(h.dtype).eps * h.max()] = 0sumh = h.sum()if sumh != 0:win = h / sumhif scale > 1:ref = convolve2d(ref, np.rot90(win, 2), mode='valid')dist = convolve2d(dist, np.rot90(win, 2), mode='valid')ref = ref[::2, ::2]dist = dist[::2, ::2]mu1 = convolve2d(ref, np.rot90(win, 2), mode='valid')mu2 = convolve2d(dist, np.rot90(win, 2), mode='valid')mu1_sq = mu1 * mu1mu2_sq = mu2 * mu2mu1_mu2 = mu1 * mu2sigma1_sq = convolve2d(ref * ref, np.rot90(win, 2), mode='valid') - mu1_sqsigma2_sq = convolve2d(dist * dist, np.rot90(win, 2), mode='valid') - mu2_sqsigma12 = convolve2d(ref * dist, np.rot90(win, 2), mode='valid') - mu1_mu2sigma1_sq[sigma1_sq < 0] = 0sigma2_sq[sigma2_sq < 0] = 0g = sigma12 / (sigma1_sq + eps)sv_sq = sigma2_sq - g * sigma12g[sigma1_sq < eps] = 0sv_sq[sigma1_sq < eps] = sigma2_sq[sigma1_sq < eps]sigma1_sq[sigma1_sq < eps] = 0g[sigma2_sq < eps] = 0sv_sq[sigma2_sq < eps] = 0sv_sq[g < 0] = sigma2_sq[g < 0]g[g < 0] = 0sv_sq[sv_sq <= eps] = epsnum += np.sum(np.log10(1 + g * g * sigma1_sq / (sv_sq + sigma_nsq)))den += np.sum(np.log10(1 + sigma1_sq / sigma_nsq))vifp = num / denif np.isnan(vifp):return 1.0else:return vifp

这段代码定义了一个类方法VIFF,用于计算两个图像(image_F和image_A或image_B)之间的视觉信息量(Visual Information Fidelity,简称VIFF)。VIFF是一种图像质量评估方法,用于比较两幅图像的相似性。

  1. @classmethod注解表明这是一个类方法,可以直接通过类名调用,而不需要实例化对象。

  2. cls.input_check(image_F, image_A, image_B):是用于检查输入图像的尺寸和类型是否正确,确保可以进行后续计算。

  3. compare_viff(ref, dist)是一个内部函数,计算两个图像(ref和dist)的VIFF值: a. sigma_nsq 和 eps 是常数,分别用于计算中的稳定性和避免除以零。 b. 通过循环(for scale in range(1, 5))对图像进行不同尺度的低通滤波(Gaussian kernel),这有助于减少噪声影响。 c. 计算每个尺度下的均值(mu1, mu2)、均值的平方(mu1_sq, mu2_sq)、协方差(sigma12)、方差(sigma1_sq, sigma2_sq)。 d. 计算相关系数(g),并根据sigma_nsqeps进行调整。 e. 计算VIFF值(vifp),即信息增益(num)除以信息冗余(den)。 f. 如果计算出的VIFF值是NaN,返回1.0(可能是为了处理异常情况),否则返回计算出的VIFF值。

总的来说,这段代码是用于评估两个图像之间在不同尺度下相似性的算法,结果范围在0到1之间,1表示完全相同,0表示完全不同。

11.Qabf(Quality Assessment Based on Fusion)

Qabf是一种新颖的融合图像客观非参考质量评估指标,得到Qabf的算法利用局部度量来估计来自输入的显着信息在融合图像中的表现程度,Qabf的值越高,表示融合图像的质量越好。计算公式如下:

详细可见见论文A new quality metric for image fusion 

代码如下:(越大越好,输入三幅图片) 
@classmethoddef Qabf(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)gA, aA = cls.Qabf_getArray(image_A)gB, aB = cls.Qabf_getArray(image_B)gF, aF = cls.Qabf_getArray(image_F)QAF = cls.Qabf_getQabf(aA, gA, aF, gF)QBF = cls.Qabf_getQabf(aB, gB, aF, gF)# 计算QABFdeno = np.sum(gA + gB)nume = np.sum(np.multiply(QAF, gA) + np.multiply(QBF, gB))return nume / deno@classmethoddef Qabf_getArray(cls,img):# Sobel Operator Sobelh1 = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]).astype(np.float32)h2 = np.array([[0, 1, 2], [-1, 0, 1], [-2, -1, 0]]).astype(np.float32)h3 = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]).astype(np.float32)SAx = convolve2d(img, h3, mode='same')SAy = convolve2d(img, h1, mode='same')gA = np.sqrt(np.multiply(SAx, SAx) + np.multiply(SAy, SAy))aA = np.zeros_like(img)aA[SAx == 0] = math.pi / 2aA[SAx != 0]=np.arctan(SAy[SAx != 0] / SAx[SAx != 0])return gA, aA@classmethoddef Qabf_getQabf(cls,aA, gA, aF, gF):L = 1Tg = 0.9994kg = -15Dg = 0.5Ta = 0.9879ka = -22Da = 0.8GAF,AAF,QgAF,QaAF,QAF = np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA),np.zeros_like(aA)GAF[gA>gF]=gF[gA>gF]/gA[gA>gF]GAF[gA == gF] = gF[gA == gF]GAF[gA <gF] = gA[gA<gF]/gF[gA<gF]AAF = 1 - np.abs(aA - aF) / (math.pi / 2)QgAF = Tg / (1 + np.exp(kg * (GAF - Dg)))QaAF = Ta / (1 + np.exp(ka * (AAF - Da)))QAF = QgAF* QaAFreturn QAF
  1. Qabf 方法接收三个输入图像(image_Fimage_Aimage_B),首先进行输入检查,然后分别计算每个图像的梯度(gAgBgF)和方向(aAaBaF)。

  2. Qabf_getArray 方法使用Sobel算子计算图像的梯度和方向。Sobel算子用于检测图像边缘,h1h2, 和 h3 是用于计算x和y方向导数的滤波器。然后计算梯度的模(gA 和 gB),以及方向(aA 和 aB)。

  3. Qabf_getQabf 方法计算Qabf值。它涉及到以下几个关键计算:

    • LTgkgDgTaka, 和 Da 是预设的参数,用于调整Qabf的计算。
    • GAF 是融合梯度的调整,根据gAgF的大小关系进行调整,以确保融合后的梯度不会过大或过小。
    • AAF 是角度差的调整,考虑了输入图像A和融合图像F的方向差异。
    • QgAF 和 QaAF 分别是基于梯度和角度调整的Q值。
    • 最终通过 QAF = QgAF * QaAF 计算出融合图像的Qabf值。
  4. QAF 是返回的结果,表示输入图像A在融合图像F中的表现程度,值越高,表明融合质量越好。

12.SSIM(结构相似性指标 Structural Similarity Index Measure, SSIM )

是一种用于比较两幅图像相似度的指标,它考虑了亮度、对比度和结构三个方面的信息。

SSIM值的范围在[-1, 1]之间,值越接近1表示两幅图像越相似,值越接近-1表示两幅图像越不相似,值为0表示两幅图像完全不同。

SSIM指标的计算基于以下三个因素:

  1. 亮度相似性(Luminance Similarity):衡量图像的亮度信息是否一致。
  2. 对比度相似性(Contrast Similarity):衡量图像的对比度信息是否一致。
  3. 结构相似性(Structure Similarity):衡量图像的结构信息是否一致。

其次就是MSSIM,这个很容易理解就是源图像A与融合图像F的SSIM与源图像B与融合图像F的SSIM的平均值。

其次是多层级结构相似性(Multiscale structural similarity),简写为MS-SSIM。MS-SSIM能更好地与人眼视觉系统的视觉感知相一致,并且在一定的尺度下,评价效果优于SSIM,公式如下:

 代码如下:(越接近1越好,输入三幅图像)
    @classmethoddef SSIM(cls, image_F, image_A, image_B):cls.input_check(image_F, image_A, image_B)return ssim(image_F,image_A)+ssim(image_F,image_B)

参考:图像融合质量评价方法MSSIM、MS-SSIM、FS、Qmi、Qabf与VIFF(三)-CSDN博客

图像融合质量评价方法AG、SF、STD、MI与NMI(二)_nmi图像-CSDN博客 

图像融合评估指标Python版_图像融合评价指标python-CSDN博客 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3016275.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

晶振负载对系统有什么影响?

电子系统中&#xff0c;晶振&#xff08;晶体振荡器&#xff09;是确保系统各部分同步工作的关键组件。然而&#xff0c;晶振的性能受到其负载电容大小的显著影响。本文将详细探讨晶振负载电容对系统性能的影响&#xff0c;并给出相应的解决方案。 一、晶振负载电容的作用 晶…

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

&#x1f496; Brief&#xff1a;大家好&#xff0c;我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 个人说明书&#xff1a;Zeeland&…

Linux高级学习(前置 在vmware安装centos7.4)

【小白入门 通俗易懂】2021韩顺平 一周学会Linux 此文章包含第006p-第p007的内容 操作 在安装好的vmware下进行安装 这里使用的是vmware15&#xff08;win10下&#xff09;&#xff0c;win11可能无法使用15&#xff08;有几率蓝屏&#xff09;&#xff0c;换成16就行了 用迅雷…

ogv转mp4怎么转?只需3个步骤~

OGV&#xff08;Ogg Video&#xff09;是一种开源的视频文件格式&#xff0c;起源于对数字媒体领域的开放标准的需求。作为Ogg多媒体容器的一部分&#xff0c;OGV的设计初衷是提供一种自由、高质量的视频编码方案&#xff0c;以满足多样化的应用需求。 支持打开MP4文件格式的软…

[蓝桥杯]真题讲解:班级活动(贪心)

[蓝桥杯]真题讲解&#xff1a;班级活动&#xff08;贪心&#xff09; 一、视频讲解二、正解代码1、C2、python33、Java 一、视频讲解 [蓝桥杯]真题讲解&#xff1a;班级活动&#xff08;贪心&#xff09; 二、正解代码 1、C #include<bits/stdc.h> using namespace st…

欢迎参展GASITC2024成都国际城市燃气智能应用技术展

GASITC2024中国&#xff08;成都&#xff09;国际城市燃气智能应用技术展览会 2024China City Gas Intelligent Application Technology Exhibition 同期召开&#xff1a;第十五届&#xff08;成都&#xff09;国际化工技术及装备展览会 展出地点&#xff1a;成都世纪城新国…

软件实施方案Word原件2024(全套软件资料包)

1.概述 2.项目介绍 3.项目实施 4.实施计划 5.人员培训 6.项目验收 7.售后服务 8.项目保障措施 软件资料清单列表部分文档&#xff08;全套可获取&#xff09;&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书…

SolidWorks进行热力学有限元分析一、模型建立

1.话不多说按照我的操作来 2.这一步鼠标移到中心点直接拉就行 3.这里选单位&#xff0c;继续按照操作来 4.选中这个边&#xff0c;直接拉&#xff0c;输入尺寸后确定&#xff0c;其他边同理 5.鼠标右键设置厚度 6.右键零件&#xff0c;然后编辑材料&#xff0c;给他赋予你需要的…

MySQL之聚合函数与应用

1. 前言 上文我们讲到了单行函数.实际上SQL还有一类叫做聚合函数, 它是对一组数组进行汇总的函数, 输入的是一组数据的集合, 输出的是单个值. 2. 聚合函数 用于处理一组数据, 并对一组数据返回一个值. 有如下几种聚合函数 : AVG(), SUM(), MAX(), MIN(), COUNT(). 3. AVG(…

(三)JSP教程——JSP动作标签

JSP动作标签 用户可以使用JSP动作标签向当前输出流输出数据&#xff0c;进行页面定向&#xff0c;也可以通过动作标签使用、修改和创建对象。 <jsp:include>标签 <jsp:include>标签将同一个Web应用中静态或动态资源包含到当前页面中。资源可以是HTML、JSP页面和文…

B端UX/UI设计面试作品集分层源文件figmasketch模板

当您考虑找工作时&#xff0c;是否曾质疑过项目复盘作品集的重要性&#xff1f;实际上&#xff0c;一份精心准备的项目复盘作品集对于求职者来说具有无可估量的价值&#xff0c;特别是对于设计师这一职业领域。 以下所述或许对您而言已非陌生。您的作品集应当成为您专业技能与…

Stable Diffusion:AI绘画的新纪元

摘要&#xff1a; Stable Diffusion&#xff08;SD&#xff09;作为AI绘画领域的新星&#xff0c;以其开源免费、强大的生成能力和高度的自定义性&#xff0c;正在引领一场艺术与技术的革命。本文旨在为读者提供Stable Diffusion的全面介绍&#xff0c;包括其原理、核心组件、安…

解决Pyppeteer下载chromium慢或者失败的问题[INFO] Starting Chromium download.

文章目录 1.进入网址2.选择上面对应自己系统的文件夹进去3. 然后找到自己的python环境中的site-packages中pyppeteer中的chromium_downloader.py文件并打开 在首次使用Pyppeteer时需要下载chromium 1.进入网址 https://registry.npmmirror.com/binary.html?pathchromium-bro…

裸辞、裁员、老板跑路、被迫失业,未来是「超级个体」的时代

本期我们邀请的程序员是张立强&#xff0c;裸辞、裁员、老板跑路、被迫失业&#xff0c;管理层利益争夺&#xff0c;职业转型&#xff0c;工作五年&#xff0c;攒出了十年经验。程序员如何寻找自己的第二曲线&#xff0c;不妨听听立强的看法。 裸辞失业 大家好&#xff0c;我…

SparkSQL与Hive整合 、SparkSQL函数操作

SparkSQL与Hive整合 SparkSQL和Hive的整合&#xff0c;是一种比较常见的关联处理方式&#xff0c;SparkSQL加载Hive中的数据进行业务处理&#xff0c;同时将计算结果落地回Hive中。 整合需要注意的地方 1)需要引入hive的hive-site.xml&#xff0c;添加classpath目录下面即可…

【牛客】【模板】二维前缀和

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 二维前缀和板题。 二维前缀和&#xff1a;pre[i][j]a[i][j]pre[i-1][j]pre[i][j-1]-pre[i-1][j-1]; 子矩阵 左上角为(x1,y1) 右下角(x2,y2…

您的浏览器不支持 undefined 代理认证!如有问题请联系您的浏览器支持,请勿反馈此问题给 SwitchyOmega.

一、【问题描述】 PAC 文件是一个 JavaScript 文件&#xff0c;用于定义客户端的代理规则。您可以在 PAC 文件中编写规则&#xff0c;根据不同的目标网址或其他条件&#xff0c;决定是否通过代理服务器进行访问。您可以将 PAC 文件部署到服务器上&#xff0c;并在客户端配置浏…

Http协议解读,运营商劫持

上一篇文章中写到了TCP协议的一些特点&#xff0c;这篇文章对http协议的大体内容做出一些解释&#xff0c;同时&#xff0c;更详细的协议参照RFC文档。这里写官方一点 http协议(超文本传输协议HyperText Transfer Protocol)&#xff0c;它是基于TCP协议的应用层传输协议&#…

OpenCV 入门(五) —— 人脸识别模型训练与 Windows 下的人脸识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

Flask-大体了解介绍

初识Flask Flask是使用 Python编写的Web微框架。Web框架可以让我们不用关心底层的请求响应处理&#xff0c;更方便高效地编写Web程序。 Flask主要有两个依赖&#xff0c;一个是WSGI&#xff08;Web Server Gateway Interface&#xff0c;Web服务器网关接口&#xff09;工具集…