大家好,我是reedsways,最近大概做了三篇paper的工作,都和图像融合有关,因此,特意搞一个帖子来记录一下,那些常用的图像融合的量化指标!
首先,就是PSNR和SSIM的技术指标:
首先介绍一下:


直接上自用代码:
from tqdm import tqdm
import torch
import os
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import numpy as np
import cv2
from skimage.metrics import peak_signal_noise_ratio as psnr_loss
from skimage.metrics import structural_similarity as ssim_loss
import argparse
#直接在这里修改!!!!!!!!!!!
parser = argparse.ArgumentParser(description='PSNR SSIM script', add_help=False)
parser.add_argument('--input_images_path', default='./图片名字')
parser.add_argument('--image2smiles2image_save_path', default='./另一个图片的名字')
args = parser.parse_args()
def is_png_file(filename):
return any(filename.endswith(extension) for extension in [".jpg", ".png", ".bmp"])
def load_img(filepath):
img = cv2.cvtColor(cv2.imread(filepath), cv2.COLOR_BGR2RGB)
img = img.astype(np.float32)
img = img / 255.
return img
class DataLoaderVal(Dataset):
def __init__(self, target_transform=None):
super(DataLoaderVal, self).__init__()
self.target_transform = target_transform
gt_dir = args.input_images_path
input_dir = args.image2smiles2image_save_path
clean_files = sorted(os.listdir(os.path.join(gt_dir)))
noisy_files = sorted(os.listdir(os.path.join(input_dir)))
self.clean_filenames = [os.path.join(gt_dir, x) for x in clean_files if is_png_file(x)]
self.noisy_filenames = [os.path.join(input_dir, x) for x in noisy_files if is_png_file(x)]
self.tar_size = len(self.clean_filenames)
def __len__(self):
return self.tar_size
def __getitem__(self, index):
tar_index = index % self.tar_size
clean = torch.from_numpy(np.float32(load_img(self.clean_filenames[tar_index])))
noisy = torch.from_numpy(np.float32(load_img(self.noisy_filenames[tar_index])))
clean_filename = os.path.split(self.clean_filenames[tar_index])[-1]
noisy_filename = os.path.split(self.noisy_filenames[tar_index])[-1]
clean = clean.permute(2, 0, 1)
noisy = noisy.permute(2, 0, 1)
return clean, noisy, clean_filename, noisy_filename
def get_validation_data():
return DataLoaderVal(None)
test_dataset = get_validation_data()
test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=False, num_workers=0, drop_last=False)
if __name__ == '__main__':
psnr_val_rgb = []
ssim_val_rgb = []
for ii, data_test in enumerate(tqdm(test_loader), 0):
rgb_groundtruth = data_test[0].numpy().squeeze().transpose((1, 2, 0))
rgb_restored = data_test[1].cuda()
rgb_restored = torch.clamp(rgb_restored, 0, 1).cpu().numpy().squeeze().transpose((1, 2, 0))
psnr_val_rgb.append(psnr_loss(rgb_restored, rgb_groundtruth))
ssim_val_rgb.append(ssim_loss(rgb_restored, rgb_groundtruth, multichannel=True))
psnr_val_rgb = sum(psnr_val_rgb) / len(test_dataset)
ssim_val_rgb = sum(ssim_val_rgb) / len(test_dataset)
print("PSNR: %f, SSIM: %f " % (psnr_val_rgb, ssim_val_rgb))
接下来就是一些非参考的评价指标!!包括了! Brenner、Laplacian、SMD、SMD2、Variance、Energy、Vollath and Entropy!
直接上代码(都是值越大越好):
import cv2
import numpy as np
import math
# brenner梯度函数计算
def brenner(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
shape = np.shape(img)
out = 0
for x in range(0, shape[0] - 2):
for y in range(0, shape[1]):
out += (int(img[x + 2, y]) - int(img[x, y])) ** 2
return out
# Laplacian梯度函数计算
def Laplacian(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
return cv2.Laplacian(img, cv2.CV_64F).var()
# SMD梯度函数计算
def SMD(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
shape = np.shape(img)
out = 0
for x in range(1, shape[0] - 1):
for y in range(0, shape[1]):
out += math.fabs(int(img[x, y]) - int(img[x, y - 1]))
out += math.fabs(int(img[x, y] - int(img[x + 1, y])))
return out
# SMD2梯度函数计算
def SMD2(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
shape = np.shape(img)
out = 0
for x in range(0, shape[0] - 1):
for y in range(0, shape[1] - 1):
out += math.fabs(int(img[x, y]) - int(img[x + 1, y])) * math.fabs(int(img[x, y] - int(img[x, y + 1])))
return out
# 方差函数计算
def variance(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
out = 0
u = np.mean(img)
shape = np.shape(img)
for x in range(0, shape[0]):
for y in range(0, shape[1]):
out += (img[x, y] - u) ** 2
return out
# energy函数计算
def energy(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
shape = np.shape(img)
out = 0
for x in range(0, shape[0] - 1):
for y in range(0, shape[1] - 1):
out += ((int(img[x + 1, y]) - int(img[x, y])) ** 2) * ((int(img[x, y + 1] - int(img[x, y]))) ** 2)
return out
# Vollath函数计算
def Vollath(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
shape = np.shape(img)
u = np.mean(img)
out = -shape[0] * shape[1] * (u ** 2)
for x in range(0, shape[0] - 1):
for y in range(0, shape[1]):
out += int(img[x, y]) * int(img[x + 1, y])
return out
# entropy函数计算
def entropy(img):
'''
:param img:narray 二维灰度图像
:return: float 图像越清晰越大
'''
out = 0
count = np.shape(img)[0] * np.shape(img)[1]
p = np.bincount(np.array(img).flatten())
for i in range(0, len(p)):
if p[i] != 0:
out -= p[i] * math.log(p[i] / count) / count
return out
def main(img1):
print('Brenner', brenner(img1) * 1e-6 )
print('Laplacian', Laplacian(img1) * 1e-2 )
print('SMD', SMD(img1) * 1e-5 )
print('SMD2', SMD2(img1) * 1e-5 )
print('Variance', variance(img1) * 1e-7 )
print('Energy', energy(img1) * 1e-8 )
print('Vollath', Vollath(img1) * 1e-7 )
print('Entropy', entropy(img1))
if __name__ == '__main__':
# 读入原始图像
img1 = cv2.imread('input_images/name.jpg')
# 灰度化处理
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
main(img1)
最后最后,超级常用的四个参数!
信息熵!
import cv2
import numpy as np
import math
tmp = []
for i in range(256):
tmp.append(0)
val = 0
k = 0
res = 0
# 'img/1-3.jpg'=6.0404 ; out2.jpg=7.0361 ;result2=7.1585
image = cv2.imread('input_images/name.jpg', 0)
img = np.array(image)
for i in range(len(img)):
for j in range(len(img[i])):
val = img[i][j]
tmp[val] = float(tmp[val] + 1)
k = float(k + 1)
for i in range(len(tmp)):
tmp[i] = float(tmp[i] / k)
for i in range(len(tmp)):
if (tmp[i] == 0):
res = res
else:
res = float(res - tmp[i] * (math.log(tmp[i]) / math.log(2.0)))
print(res)
均值和标准差!
from PIL import Image, ImageStat
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('input_images/name.jpg')
img = img.astype(np.float32) / 255
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# plt.imshow(img)
cv2.imshow('img', img)
# 通过img.copy()方法,复制img的数据到mean_img
mean_img = img.copy()
# 使用 .mean() 方法可得出 mean_img 的平均值
print(mean_img.mean())
# mean_img -= mean_img.mean() 等效于 mean_img = mean_img - mean_img.mean()
# 减去平均值,得出零平均值矩阵
mean_img -= mean_img.mean()
# 显示图像
# cv2.imshow(mean_img)
cv2.imshow('mean_img', mean_img)
std_img = mean_img.copy()
# 输出 std_img 的标准差
print(std_img.std())
# std_img /= std_img.mean() 等效于 std_img = std_img / std_img.mean()
# 除于标准差,得出单位方差矩阵
std_img /= std_img.std()
# 显示图像
# plt.imshow(std_img)
cv2.imshow('std_img', std_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
平均梯度!
import cv2 as cv
import numpy as np
'''图像梯度(由x,y方向上的偏导数和偏移构成),有一阶导数(sobel算子)和二阶导数(Laplace算子)
用于求解图像边缘,一阶的极大值,二阶的零点
一阶偏导在图像中为一阶差分,再变成算子(即权值)与图像像素值乘积相加,二阶同理
'''
def sobel_demo(image):
grad_x = cv.Sobel(image, cv.CV_32F, 1, 0) # 采用Scharr边缘更突出
grad_y = cv.Sobel(image, cv.CV_32F, 0, 1)
gradx = cv.convertScaleAbs(grad_x) # 由于算完的图像有正有负,所以对其取绝对值
grady = cv.convertScaleAbs(grad_y)
# 计算两个图像的权值和,dst = src1alpha + src2beta + gamma
gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
cv.imshow("gradx", gradx)
cv.imshow("grady", grady)
cv.imshow("gradient", gradxy)
def laplace_demo(image): # 二阶导数,边缘更细
dst = cv.Laplacian(image, cv.CV_32F)
lpls = cv.convertScaleAbs(dst)
cv.imshow("laplace_demo", lpls)
def custom_laplace(image):
# 以下算子与上面的Laplace_demo()是一样的,增强采用np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
dst = cv.filter2D(image, cv.CV_32F, kernel=kernel)
lpls = cv.convertScaleAbs(dst)
cv.imshow("custom_laplace", lpls)
def Scharr(img):
scharrx = cv.Scharr(img, cv.CV_64F, dx=1, dy=0)
scharrx = cv.convertScaleAbs(scharrx)
scharry = cv.Scharr(img, cv.CV_64F, dx=0, dy=1)
scharry = cv.convertScaleAbs(scharry)
result = cv.addWeighted(scharrx, 0.5, scharry, 0.5, 0)
cv.imshow("scharrx", scharrx)
cv.imshow("scharry", scharry)
cv.imshow("result", result)
src = cv.imread("input_images/name.jpg")
cv.imshow("original", src)
sobel_demo(src)
laplace_demo(src)
# custom_laplace(src)
Scharr(src)
cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
cv.destroyAllWindows() # 关闭所有窗口