基于空域直方图和频谱分析图像超分辨率恢复
本篇博客主要记录下对超分辨率恢复后的图像从空域和频域的特征进行比较和个人的看法。
目录
1. 基于空域角度
1.1 图像空域直方图
图像的直方图处理是从概率统计的角度出发,对图像灰度级的概率分布进行变换,从而达到使图像细节丰富、动态范围较大、便于观测和理解的目的。
直方图处理是多种空间域处理技术的基础,可以直接用于图像的增强以及图像的压缩和分割。在灰度级范围为[0,L-1]的数字图像的直方图可以表示为:
p
(
r
k
)
=
n
k
/
(
M
×
N
)
p(r_k) = n_k /(M\times N)
p(rk)=nk/(M×N)
其中
r
k
r_k
rk是灰度级,
n
k
n_k
nk是灰度级为
r
k
r_k
rk的像素的个数,
M
,
N
M,N
M,N是图像矩阵的长和宽。
因此图像空域的直方图可以直观地反应出图像像素的分布。
1.2 重构图像前后的直方图统计特性
由图像的直方图特征可以看出,图像在空域的像素分布情况,基于8位的图像像素值是[0,255]之间。首先我是用双三次插值对低分辨率图像进行恢复,观察通过双三次插值恢复的图像和原始高分辨率图像之间的直方图分布。
首先获取低分辨率图像,经典的美女Lena图哈哈。。。计算其直方图分布和原始高分辨率的图像直方图进行对比。
图1 低分辨率图像,降采样倍数为4
图2:空域直方图分布
来源于本作者实验
图2的解释:
(1)红色的图是原始高分辨率图像,绿色是经过双三次插值后的恢复图像,蓝色是低分辨率图像的直方图分布。放大倍数是4,x轴是像素灰度等级,y轴是某一个灰度等级上的像素的个数。
(2)可以看到,低分辨率直方图和红色原始高分辨率直方图相比,基本的轮廓分布已经很难相似,可以将低分辨率图像的直方图理解为在高分辨率直方图上的间隔采样。当使用双三次插值恢复的时候,轮廓可以很好的接近于原始高分辨率图像直方图。但是细节上还是有差距的,在空域上就是高频分量的损失。
事实上,所有的插值方法只能恢复低频信息,无法恢复高频信息。所以超分辨率算法使用深度学习也好,传统方法【稀疏编码,自相似性,领域回归,增加先验项等等】都是为了恢复高频分量。
图例2代码:
# 图1代码
img = cv2.imread("lena.tiff")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
height, width = img_gray.shape
# plt.imshow(img_gray,cmap = plt.cm.gray)
hist_original = cv2.calcHist([img_gray], [0], None, [256], [0, 256])
# bicubic downsampling + gaussian blur
down_size = (int(width * 0.25), int(height * 0.25))
img_gray_bicubic_down = cv2.resize(img_gray, down_size, interpolation=cv2.INTER_CUBIC)
img_gray_bicubic_down_blur = cv2.GaussianBlur(img_gray_bicubic_down, (5, 5), sigmaX=0, sigmaY=0)
# img_gray_bicubic_down_blur = cv2.cvtColor(img_gray_bicubic_down_blur,cv2.COLOR_BGR2GRAY)# 转化为RGB
plt.figure()
plt.imshow(img_gray_bicubic_down, cmap=plt.cm.gray)
cv2.imwrite("degradation_image.bmp", img_gray_bicubic_down_blur)
hist_bicubic_down = cv2.calcHist([img_gray_bicubic_down_blur], [0], None, [256], [0, 256])
up_size = (int(down_size[0] * 4), int(down_size[1] * 4))
print("up size is ", up_size)
img_gray_bicubic_up = cv2.resize(img_gray_bicubic_down, up_size, interpolation=cv2.INTER_CUBIC)
hist_bicubic_up = cv2.calcHist([img_gray_bicubic_up], [0], None, [256], [0, 256])
plt.figure()
plt.title("compare histogram")
plt.xlabel("Bins")
plt.ylabel("Pixels")
plt.plot(hist_original,color='r',label='original histogram')
plt.xlim([0,256])
plt.plot(hist_bicubic_down,color='b',label="LR histogram")
plt.plot(hist_bicubic_up,color='g',label="upsampling histogram",linewidth=2,linestyle='-.')
plt.savefig('./result_x4.tif',dpi=600)
plt.grid(True)
plt.legend()
plt.show()
2. 基于频域的角度
2.1 二维傅里叶变换,频谱
公式1:来源于本作者
经过二维傅里叶变换得到的频谱图中心是低频信息,有中心向四周扩散的是高频信息。
具体的介绍请参看其他博客或者书籍,这里不再一一详细介绍。
2.2 重构图像和原始图像的频谱系数分布
我们来可视化经过网络恢复的高分辨率图像的频谱和原始高分辨率图像的频谱之间的差异。
首先看下2维频谱图:
图3:二维频谱图
来源于本作者实验
再来看下3维频谱图:
图4:三维频谱图,该频谱图用到的图像是下面的图5测试集
来源于本作者实验
中间凸起来的就是低频分量,能量最高,代表该图像的低频信息更多,事实上,一幅自然图像的轮廓信息占了大多数。和二维频谱图是一样的。
下面考察经过网络恢复后的图像和原始Ground Truth图像频谱之间的关系:
图5是使用的测试集图像
图5: Ground Truth ,图像来源于测试集Set 14
图6: 经过网络恢复的高分辨率图像
>来源于本作者实验
图7:重构图像的频谱分布图,即图6的三维频谱分布图
来源于本作者实验
为了更好查看频谱差异,我将3维频谱图的一个维度收取出来进行可视化。如图8所示:
图8:蓝线是原始图像图5的频谱的一个维度图,红线是图6的频谱的一个维度图。
来源于本作者实验
从图4和图7来看,重构前后的3维频谱图可以看出,两者之间的分布趋势是相同的,可以理解为在数据保真度上满足收敛于原始GT图像,但是分布的细节上(高频分量的分布上)存下差异,主要表现在:
-
重构图像的频谱学习到了原始图像的频谱分布趋势,但是有些频率或者频率区间上学习的太“过”了,能量系数高出原始频谱;或者学习的太“欠”了,能量系数小于真实能量系数。这一部分个人认为是可以接受的,从损失函数上说,重构前后的误差只需要在以 l 2 l_2 l2 范数准则下误差收敛即可。
-
若想进一步改进。从频谱来看,能量系数在有些频率区间的误差可以通过以下几个方面入手试试【只是个人的猜测和想法,以后会做实验验证】:
(1) 改进网络结构,从训练参数入手; (2) 从损失函数入手,设计满足合适的损失函数使得误差收敛更接近于0; (3) 从频率的角度探索DNN的学习能力,并尝试。。。