pytorch torch.nn.functional实现插值和上采样

时间:2024-03-07 15:46:46

图像的插值算法

最近邻插值

这是一种简单的插值算法:不需要计算,在待求象素的四邻象素中,将距离待求象素最近的邻象素灰度赋给待求象素

设i+u, j+v(i, j为正整数, u, v为大于零小于1的小数,下同)为待求象素坐标,则待求象素灰度的值 f(i+u, j+v)

如下图所示:

 

 

如果(i+u, j+v)落在A区,即u<0.5, v<0.5,则将左上角象素的灰度值赋给待求象素,同理,落在B区则赋予右上角的象素灰度值,落在C区则赋予左下角象素的灰度值,落在D区则赋予右下角象素的灰度值。
最邻近元法计算量较小,但可能会造成插值生成的图像灰度上的不连续,在灰度变化的地方可能出现明显的锯齿状

 

tf.image.resize_nearest_neighbor(
images,
size,
align_corners=False,
name=None
)

使用最近邻插值调整images为size.

参数:

images:一个Tensor,必须是下列类型之一:int8,uint8,int16,uint16,int32,int64,half,float32,float64.4-D与形状[batch, height, width, channels].
size:2个元素(new_height, new_width)的1维int32张量,表示图像的新大小.
align_corners:可选的bool,默认为False,如果为True,则输入和输出张量的4个角像素的中心对齐,并保留角落像素处的值.
name:操作的名称(可选).
返回:

 

 

 

基本原理
最简单的图像缩放算法就是最近邻插值。顾名思义,就是将目标图像各点的像素值设为源图像中与其最近的点。算法优点在与简单、速度快。

如下图所示,一个4*4的图片缩放为8*8的图片。步骤:

生成一张空白的8*8的图片,然后在缩放位置填充原始图片值(可以这么理解)

在图片的未填充区域(黑色部分),填充为原有图片最近的位置的像素值。

import cv2
import numpy as np


def nearest_neighbor_resize(image, target_size):
   """
   Nearest Neighbour interpolate for RGB  image

   :param image: rgb image
   :param target_size: tuple = (height, width)
   :return: None
   """

   # 1:按照尺寸创建目标图像
   target_image = np.zeros(shape=(*target_size, 3))
   # 2:计算height和width的缩放因子
   alpha_h = target_size[0] / image.shape[0]
   alpha_w = target_size[1] / image.shape[1]

   for tar_x in range(target_image.shape[0] - 1):
      for tar_y in range(target_image.shape[1] - 1):
         # 3:计算目标图像人任一像素点
         # target_image[tar_x,tar_y]需要从原始图像
         # 的哪个确定的像素点image[src_x, xrc_y]取值
         # 也就是计算坐标的映射关系
         src_x = round(tar_x / alpha_h)
         src_y = round(tar_y / alpha_w)

         # 4:对目标图像的任一像素点赋值
         target_image[tar_x, tar_y] = image[src_x, src_y]

   return target_image


def test():
    img_path = \'E:\clcode\PASSRnet-master\PASSRnet-master\hr0.png\'

    # img_path = \'/root/userfolder/cl/PASSRnet-master/PASSRnet-master/hr0.png\'
    img = cv2.imread(img_path)
    print(img.shape)
    ret_img = nearest_neighbor_resize(img, (600, 2800))

    cv2.imshow("source image", img)
    cv2.imshow("after bilinear image", ret_img)



def main():
   test()


if __name__ == \'__main__\':
    main()

 

 

 

 

2.双线性插值

tf.image.resize_bilinear函数

tf.image.resize_bilinear(
    images,
    size,
    align_corners=False,
    name=None
)

 

使用双线性插值调整images为size.

输入图像可以是不同的类型,但输出图像总是浮点型的.

参数:

  • images:一个Tensor,必须是下列类型之一:int8,uint8,int16,uint16,int32,int64,bfloat16,half,float32,float64;4维的并且具有形状[batch, height, width, channels].
  • size:2个元素(new_height, new_width)的1维int32张量,用来表示图像的新大小.
  • align_corners:可选的bool,默认为False;如果为True,则输入和输出张量的4个角像素的中心对齐,并且保留角落像素处的值.
  • name:操作的名称(可选).

返回值:

该函数返回float32类型的Tensor.

 

 

import cv2
import numpy as np
import  tensorflow as tf
img= cv2.imread(\'./style_imgs/10.png\')
cv2.imshow(\'svf\',img)
imgInfo = img.shape
#(height,width,mode) = imgInfo
# dstHeight = int(height/2)
# dstWidth = int(width/2)
# dstImg = np.zeros((dstHeight,dstWidth,3),np.uint8)
print(imgInfo)
# for i in range(0,dstHeight):
#     for j in range(0,dstWidth):
#         #左上角的点坐标为a和 b
#         a = int(i*(height/dstHeight))
#         b = int(j*(width/dstWidth))
#         rH= i*(height/dstHeight) - a
#         rW= j*(width/dstWidth) - b
#         dstImg[i,j] = (1-rW)*(1-rH)*img[a,b] + (1-rW)*(rH)*img[a+1,b] + (rW)*(1-rH)*img[a,b+1] + (rW)*(rH)*img[a+1,b+1];
# cv2.imshow(\'dst\',dstImg)
# cv2.waitKey(0)

 

 

转载自:https://www.cnblogs.com/wanghui-garcia/p/11399034.html

S  = torch.nn.functional.interpolate(L , scale_factor=2, mode=\'bicubic\', align_corners=False)

注意:

使用mode=\'bicubic\'时,可能会导致overshoot问题,即它可以为图像生成负值或大于255的值。

如果你想在显示图像时减少overshoot问题,可以显式地调用result.clamp(min=0,max=255)。