Image Super-resolution Reconstruction Based on Bionic Intelligence
基于仿生智能的图像超分辨率重建–理解和代码还原
说明:本文是参照20年IEEE上的一篇文章,进行阅读,理解,以及根据自己的理解进行的复现(python),因为版本问题,有些代码可能无法成功运行。我以后还会在此基础上进行改进,现在先把主要内容罗列出来。
文章作者:
Xin Wang, Qiong Wang, Guofang Lv
Jiangsu Key Laboratory of Image and Video Understanding for Social Safety,
Nanjing University of Science and Technology, Nanjing, China
College of Computer and Information, Hohai University, Nanjing, China
内容理解
主要思想:传统的超分辨率重建方法通常将低分辨率图像作为一个整体进行处理,忽略了图像块之间的差异,导致重建效果不佳。
此文章采用斑块的概念,将“斑块”作为超分辨率重构的基本单元。
此文章将生物视觉注意机制启发的方法应用于初始重建结果,以检测出显著区域(文章重点)。然后,将超分辨率卷积神经网络模型应用于显著图像块,以获得精确的重建结果
步骤:
step1:双三次插值图像重建
首先使用双三次插值法重建原始分辨率图像,得到Xinit。
step2:显著图像块提取
2.1用FT技术计算Xinit.
2.2然后自适应阈值运算得到二进制显著映射Winit。
2.3将Xinit分为n个块。基于Winit,如果至少五分之一的图像块是白色的,则将此图像块视为显著性块;否则,将Pk视为不显著的。
step3:基于SRCNN的超分辨率重建
将SRCNN分别应用于每个显著图像块
step1 双三次插值法(bicubic interpolation)
插值方法简单来说就是我们输入一个低分辨率图像,我们得到它每个像素点上的像素值,来对它进行插入,填充近一些空的像素点,通过一定的办法计算出这些空像素点的像素值。
1.此算法涉及到16个像素点,其中P00代表目标插值图中某像素点在原图中最接近的像素点。
(1.1,1.2)——>P00:(1,1)
而最终插值后的图像(x,y)的值为以下16个像素点的权重卷积之和。
2.假设源图像A大小为mn,缩放K倍后的目标图像B的大小为MN,即K=M/m。我们想要求出目标图像B中每一像素点(X,Y)的值,必须先找出像素(X,Y)在源图像A中对应的像素(x,y),再根据源图像A距离像素(x,y)最近的16个像素点作为计算目标图像B(X,Y)处像素值的参数,利用BiCubic基函数求出16个像素点的权重,图B像素(x,y)的值就等于16个像素点的加权叠加。
3.开始构造BiCubic 函数,可用以下函数近似:
# 产生16个像素点不同的权重
def BiBubic(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
4.然后我们要做的就是求出BiCubic函数中的参数x,从而获得上面所说的16个像素所对应的权重W(x)。BiCubic基函数是一维的,而像素是二维的,所以我们将像素点的行与列分开计算。BiCubic函数中的参数x表示该像素点到P点的距离,例如a00距离P(x+u,y+v)的距离为(1+u,1+v),因此a00的横坐标权重i_0=W(1+u),纵坐标权重j_0=W(1+v),a00对B(X,Y)的贡献值为:(a00像素值)* i_0* j_0。因此,a0X的横坐标权重分别为W(1+u),W(u),W(1-u),W(2-u);ay0的纵坐标权重分别为W(1+v),W(v),W(1-v),W(2-v);B(X,Y)像素值为
加权算法:
# 双三次插值算法
# dstH为目标图像的高,dstW为目标图像的宽
def BiCubic_interpolation(img,dstH,dstW): #传入原始图像/目标图像的高/目标图像的宽
scrH,scrW,_=img.shape #获取原图像的高度和宽度
#img=np.pad(img,((1,3),(1,3),(0,0)),'constant')
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)
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) #产生16个像素点不同的权重
retimg[i,j]=np.clip(tmp,0,255)
return retimg
5.得到Xinit
图左是原始的低分辨率图像img。图右是用双三次插值法重建的图像Xinit。可以看出,虽然图像尺寸变大了,但还是有点模糊。
step2:显著图像块提取
2.1用FT技术计算Xinit.
原理:计算Lab空间下每点与均值的欧式距离作为显著值
note1:
Lab是由一个亮度通道(channel)和两个颜色通道组成的。在Lab颜色空间中,每个颜色用L、a、b三个数字表示,各个分量的含义是这样的:
- L代表亮度- a代表从绿色到红色的分量- b代表从蓝色到黄色的分量*
note2:
欧式距离计算
**代码**:
def FT(img):
#img = img[...,::-1] #把RGB(或BRG)转换成BGR(或者RGB)。
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #将传入的图片转成RGB格式
img = cv2.GaussianBlur(img,(5,5), 0) #第一步:高斯滤波
lab = cv2.cvtColor(img, cv2.COLOR_RGB2LAB) #第二步:转成LAB色彩空间格式
l_mean = np.average(lab[0]) #第三步:计算
a_mean = np.average(lab[1])
b_mean = np.average(lab[2])
inits = np.square(lab - np.array([l_mean, a_mean, b_mean]))
inits = np.sum(lab,axis=2)
inits = lab/np.max(lab)
return inits
2.2自适应阈值运算得到二进制显著映射Winit.
原理:根据图像不同区域亮度分布,计算其局部阈值,所以对于图像不同区域,能够自适应计算不同的阈值,因此被称为自适应阈值法。
代码:
def Adaptive(img):
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
GrayImage= cv2.medianBlur(GrayImage,5) # 中值滤波
Winit = cv2.adaptiveThreshold(GrayImage,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,3,5)
return Winit
得到Winit:
图左示出了初始重建结果的显著性映射inits,图右显示了二进制显著映射Winit。
2.3将Xinit分为n个块。基于Winit,如果至少图像块的五分之一的是白色的,则将此图像块视为显著性块;否则,将此图像块视为不显著的。
2.3.1图像分块
原理:图像分块的方法有很多,因为会遇到图片的长宽不能整除问题,这里用的是图像缩放法,如果用四舍五入法会导致判断显著性块的时候不准确。
图片缩放法:图像缩放一下,让其满足整除关系即可。
def display_blocks(divide_image):# 显示分块图片
m,n=divide_image.shape[0],divide_image.shape[1]
for i in range(m):
for j in range(n):
plt.subplot(m,n,i*n+j+1)
plt.imshow(divide_image[i,j,:])
plt.show()
plt.axis('off')
plt.title('block:'+str(i*n+j+1))
def divide_method2(img,m,n):#分割成m行n列
h, w = img.shape[0],img.shape[1]
grid_h=int(h*1.0/(m-1)+0.5)#每个网格的高
grid_w=int(w*1.0/(n-1)+0.5)#每个网格的宽
#满足整除关系时的高、宽
h=grid_h*(m-1)
w=grid_w*(n-1)
#图像缩放
img_re=cv2.resize(img,(w,h),cv2.INTER_LINEAR)# 也可以用img_re=skimage.transform.resize(img, (h,w)).astype(np.uint8)
#plt.imshow(img_re)
gx, gy = np.meshgrid(np.linspace(0, w, n),np.linspace