作业描述:python写Bicubic方法,跑数据集Set5和Set14,两个数据集都把放到倍数×2,×3,×4,×8跑一遍,最后把图像质量评估指标 PSNR 和 SSIM 保存在表格里面。
实现思路:
- 实现Bicubic方法,通过循环将数据集Set5 和 Set14 进行放大。
- 使用opencv 中的 resize()将放大后的图像进行缩放,缩放到与源图像大小一致
- 使用 PSNR 和 SSIM 对原图像和放大的图像进行图像质量评估
- 利用list将结果保存到excel表中
- 1. Bicubic(双三次插值)对图像进行缩放
- 2. 使用cv2 中的 resize() 将放大的图片进行缩放
- 3. 图像质量评估指标:PSNR和SSIM
- 4. 将运行后生成的psnr和ssim的值进行保存,生成excel表
双三次插值法数学原理参照这里:算法原理链接
代码为总结 前人的代码 进行改进:
from PIL import Image
import numpy as np
import math
import os
"""
作业:用python写Bicubic方法保存PSNR和SSIM,跑数据集Set5和Set14,两个数据集都把放到倍数×2,×3,×4,×8跑一遍,
最后把PSNR和SSIM保存在表格里面。这个作业完成时间6.26 晚上12:00前。
Bicubic是双三插值法
"""
# 产生16个像素点不同的权重
def BiBubic(x):
# 根据参考的公式 S(x) ,将其转换成代码样式
x = abs(x)
if x <= 1:
return 1-2*(x**2)+(x**3)
elif x < 2:
return 4-8*x+5*(x**2)-(x**3)
else:
return 0
# 双三次插值算法
# dstH为目标图像的高,dstW为目标图像的宽
def BiCubic_interpolation(img, dstH, dstW):
scrH, scrW, _= img.shape
retimg = np.zeros((dstH, dstW, 3), dtype=np.uint8)
for i in range(dstH):
for j in range(dstW):
scrx = i*(scrH/dstH)
scry = j*(scrW/dstW)
x = math.floor(scrx) # floor向下取整
y = math.floor(scry)
u = scrx-x
v = scry-y
tmp = 0
for ii in range(-1, 2):
for jj in range(-1, 2):
if x+ii < 0 or y+jj < 0 or x+ii >= scrH or y+jj >= scrW:
continue
tmp += img[x+ii, y+jj] * BiBubic(ii-u) * BiBubic(jj-v)
retimg[i, j] = np.clip(tmp, 0, 255)
return retimg
if __name__ == '__main__':
times = [2, 3, 4, 8]
"""
此处可以封装成函数,鉴于自己使用,就偷懒了
Set5
"""
im_path = r"./input/Set5/"
out_path = r'./output/Set5/' #事先建立好文件夹
files = os.listdir(im_path)
for i in times:
for spl_file in files:
file_name = spl_file.strip('./input/Set5,.')
print('bicl:', file_name)
image = np.array((Image.open(im_path + spl_file)))
image3 = BiCubic_interpolation(image, image.shape[0] * i, image.shape[1] * i) # i 为放大倍数
# 因为图片在imread过程中,cv2读取的结果图片形式为BRG 需要转化RGB
image3 = Image.fromarray(image3.astype('uint8')).convert('RGB')
image3.save(out_path + file_name + '_' + str(i) + '.png')
"""
Set14
"""
im_path = r"./input/Set14/"
out_path = r'./output/Set14/' #事先建立好文件夹
files = os.listdir(im_path)
for i in times:
for spl_file in files:
file_name = spl_file.strip('./input/Set14,.')
print('bicl:', file_name)
image = np.array((Image.open(im_path + spl_file)))
image4 = BiCubic_interpolation(image, image.shape[0] * i, image.shape[1] * i) # i为放大倍数
# 因为图片在imread过程中,cv2读取的结果图片形式为BRG 需要转化RGB
image4 = Image.fromarray(image4.astype('uint8')).convert('RGB')
image4.save(out_path + file_name + '_' + str(i) + '.png')
使用时,注意路径和 输出的 图片格式。
2. 使用cv2 中的 resize() 将放大的图片进行缩放为什么要做这一步?
因为在使用PSNR进行评估时所传入的image1和image2需要保持大小一致,不然会报错。
代码中,size_2,size_1为原图像的尺寸,使用时需要更改路径。
如果电脑未安装cv2,在cmd中执行以下语句即可安装(等待时间有点儿长):
pip --default-timeout=500 install -U opencv-contrib-python
import cv2
import os
if __name__ == '__main__':
#path = './input/Set14/'
#tar_path = './output/Set14/'
path = './input/Set5/'
tar_path = './output/Set5/'
folders = os.listdir(path)
print(folders)
nums = [2, 3, 4, 8]
for folder in folders:
folder_path = os.path.join(path, folder)
# print(folder_path)
img = cv2.imread(folder_path)
size_1 = img.shape[0]
size_2 = img.shape[1]
for i in nums:
out_img = folder + '_' + str(i) + '.png'
folder_tar_path = os.path.join(tar_path, out_img)
print(i)
print(folder_tar_path)
tar_img = cv2.imread(folder_tar_path)
resize = cv2.resize(tar_img, (size_2, size_1), interpolation=cv2.INTER_CUBIC) # 定尺寸的缩放
print(resize.shape)
# cv2.imwrite(r'./SetOfScale/Set14/'+ out_img, resize)
cv2.imwrite(r'./SetOfScale/Set5/' + out_img, resize)
缩放完成后,我们就得到了经过双三次插值法放大的图片与原图片一样大小的图片。
接下来就对图片进行比对,得出PSNR和SSIM的值。
图像质量评估 PSNR 和 SSIM 原理 参照此文章
代码实现主要使用了 skimage库,代码实现参考了这篇文章
实现中参杂着 将数据保存到excel中的代码,使用的是 xlwt库
import xlwt # excel表
import numpy as np
import skimage.io as io
from skimage.metrics import peak_signal_noise_ratio # PSNR
from skimage.metrics import structural_similarity # SSIM
from skimage.color import rgb2ycbcr # RGB三通道使用
import os
# 单通道 img.dtype 为 uint8 范围0-255
def Dan_PSNR_and_SSIM(path, tar_path):
folders = os.listdir(path)
nums = [2, 3, 4, 8]
results = []
print(folders)
for folder in folders:
folder_path = os.path.join(path, folder)
img = io.imread(folder_path)[..., 0]
for i in nums:
out_img = folder + '_' + str(i) + '.png'
folder_tar_path = os.path.join(tar_path, out_img)
tar_img = io.imread(folder_tar_path)[..., 0]
psnr_val = peak_signal_noise_ratio(img, tar_img)
ssim_val = structural_similarity(img, tar_img)
re = [folder, out_img, psnr_val, ssim_val]
results.append(re)
return results
# RGB 三通道 img.dtype 为 float64 需要归一化到 0-1.0
def RGB_PSNR_and_SSIM(path, tar_path):
folders = os.listdir(path)
nums = [2, 3, 4, 8]
results = []
print(folders)
# rgb2ycbcr的输入需要归一化到0-1.0的float
# 这个在上一篇blog中讲过了rgb2ycbcr输出为浮点型且范围是0-255.0 所以需要再次归一化0-1
for folder in folders:
folder_path = os.path.join(path, folder)
img = io.imread(folder_path)
img = img/255.0
img = rgb2ycbcr(img)[:, :, 0:1]
img = img/255.0
for i in nums:
out_img = folder + '_' + str(i) + '.png'
folder_tar_path = os.path.join(tar_path, out_img)
tar_img = io.imread(folder_tar_path)
tar_img = tar_img / 255.0
tar_img = rgb2ycbcr(tar_img)[:, :, 0:1]
tar_img = tar_img / 255.0
psnr_val = peak_signal_noise_ratio(img, tar_img)
ssim_val = structural_similarity(img, tar_img,win_size=11,gaussian_weights=True,multichannel=True,data_range=1.0,K1=0.01,K2=0.03,sigma=1.5)
re = [folder, out_img, psnr_val, ssim_val]
results.append(re)
return results
4. 将运行后生成的psnr和ssim的值进行保存,生成excel表
main方法,接上面代码。
def save_excel(col, set5_dan, set5_RGB, set14_dan, set14_RGB):
# 创建excel表格
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
# 奖励一张sheet表单
sheet1 = book.add_sheet('Set5_单通道', cell_overwrite_ok=True)
sheet2 = book.add_sheet('Set5_RGB三通道', cell_overwrite_ok=True)
sheet3 = book.add_sheet('Set14_单通道', cell_overwrite_ok=True)
sheet4 = book.add_sheet('Set14_RGB三通道', cell_overwrite_ok=True)
# 将列属性元组col写进 sheet表单中
for i in range(len(col)):
sheet1.write(0, i, col[i]) # 参数:行、列、col元组值
sheet2.write(0, i, col[i])
sheet3.write(0, i, col[i])
sheet4.write(0, i, col[i])
# 写数据
# sheet1
for i in range(len(set5_dan)):
data = set5_dan[i]
for j in range(len(set5_dan[0])):
sheet1.write(i + 1, j, data[j])
# sheet2
for i in range(len(set5_RGB)):
data = set5_RGB[i]
for j in range(len(set5_RGB[0])):
sheet2.write(i + 1, j, data[j])
# sheet3
for i in range(len(set14_dan)):
data = set14_dan[i]
for j in range(len(set14_dan[0])):
sheet3.write(i + 1, j, data[j])
# sheet4
for i in range(len(set14_RGB)):
data = set14_RGB[i]
for j in range(len(set14_RGB[0])):
sheet4.write(i + 1, j, data[j])
# 保存
savepath = './excel表格.xls'
book.save(savepath)
if __name__ == '__main__':
""" 循环遍历出 每个缩放后的图片的 与原图片的 PSNR 和 SSIM 值,并保存到excel中"""
path = './input/Set5/'
tar_path = './SetOfScale/Set5/'
# 单通道
Set5_dan = Dan_PSNR_and_SSIM(path,tar_path)
print("Set5_dann",Set5_dan)
Set14_dan = Dan_PSNR_and_SSIM('./input/Set14', './SetOfScale/Set14/')
print("Set14_dann",Set14_dan)
# RGB三通道
Set5_RGB= RGB_PSNR_and_SSIM(path,tar_path)
print("Set5_RGBn",Set5_RGB)
Set14_RGB = RGB_PSNR_and_SSIM('./input/Set14', './SetOfScale/Set14/')
print("Set14_RGBn",Set14_RGB)
# 自定义列名
col = ('原图片', '放大图片', 'PSNR值', 'SSIM值')
save_excel(col, Set5_dan, Set5_RGB, Set14_dan, Set14_RGB)
生成的excel表格如图:
set14数据集中,baboon.png 原图
双三次插值法 放大2倍图像:
双三次插值法放大 3倍图像:
通过对比,可以明显的看出,放大倍数越大,照片表面的像素颗粒越明显,看着就像生活中的刺绣一样。
本次的作业中,对于Bicubic方法的原理,以及使用的PSNR和SSIM评估方法公式的理解不够,下来再继续努力 --20220626



