pytorch拼接与保存图片

在深度学习训练时,我们常需要对某层的输出或最终模型的预测结果进行输出查看,如featmap、output、predict结果等。在pytorch的设定中有tensor类型变量,不可直接查看和保存图片。

 虽然有 torchvision.utils.save_image 方法可以方便地保存tensor类型图片,调用方法如下:

from torchvision.utils import save_image

save_image(tensor , filename , padding =0)

这个方法不仅可以保存图片,而且可以保存多个图片拼接后输出。但是对于不同通道不同类型,如RGB和灰度图,的图片,仍然有不方便使用的地方,于是我自己写了几个函数,适用于图片的输出保存、拼接。

from PIL import Image

def joint_img_vertical(imgs):
  # print(imgs.ndim)
  if imgs.ndim ==4:     #RGB img
    width, height = imgs[0][0].shape
    result = Image.new('L', (width, height*imgs.shape[0]))
    # Add 0.5 after unnormalizing to [0, 255] to round to nearest integer
    imgs = imgs.mul_(255).add_(0.5).clamp_(0, 255).cpu().numpy().transpose((0, 2, 3, 1))
  elif imgs.ndim ==3:   #single channel img
    width, height = imgs[0].shape
    result = Image.new('L', (width, height*imgs.shape[0]))
    imgs =imgs*255
  for i in range(imgs.shape[0]):
    im = Image.fromarray((imgs[i]).astype(np.uint8))
    result.paste(im, box=(0, i * height))

  # 取消注释以下代码可直接保存图片
  # im = Image.fromarray((img * 255).astype(np.uint8))
  # im.save(filename)
  # result.save(filename)
  return result

def joint_img_horizontal(img,output,mask):
  # print(img.size, output.size, mask.size)
  if img.size == output.size == mask.size:
    width, height = img.size
    result = Image.new('L', (width * 3, height))
    result.paste(img, box=(0, 0))
    result.paste(output, box=(width, 0))
    result.paste(mask, box=(2 * width, 0))
  return result

def save_img(img,filename):
  '''
    it is used to save an img in filename directory
  :param img: the img should be Image type .
  :param filename: like "**.png"
  '''
  img.save(filename)

 第一个函数的作用是垂直拼接一个Batch的tensor图片。我做的是一个分割任务,在我的程序中,有RGB图片(原图)和单通道图片(mask和output),对于RGB图片,维度是(batch , channel ,width ,height)。对于单通道图片,维度是(batch , width ,height)。

对于tensor类型,要转化为numpy类型,方法是tensor.cpu().numpy.transpose((0,2,3,1)) 。注意要保存为numpy后转为PIL中的Image类型。对于三通道图,要transpose为(width, height, channel )类型。

(这里我额外写了一个去Normalization的操作,个人视情况添加,我的代码中如果不添加这一步,会导致保存图片色彩失真,可能是我事先对数据做了数据增强的缘故)

第二个函数的作用是水平拼接三个Image类型的图片,即第一个函数的三个输出。这是为了将Image,output,mask三个图片放在同一个图片中做分割或检测效果对比观察。用到了new函数创建画布,paste方法粘贴图片到画布上。

Tip :查看tensor或numpy类型数组的大小尺寸。用tensor.shape 、numpy.shape ,而查看Image类型图片的大小,用img.size。

第三个函数的作用是保存Image图片类型到本地,注意只有Image类型的图片才有save方法,tensor和numpy类型的自然是没有的。因为本文对于图片的操作都用PIL来实现,所以保存图片也用的此方法。同样的思想,还可以用opencv库来实现。

同时调用以上三个函数就可以实现对一个Batch类型的图片批量拼接保存。

batch_img = joint_img_vertical(data)        #data是tensor类型
batch_output = joint_img_vertical(output)   #output是array类型
batch_mask = joint_img_vertical(predict)    #predict是array类型
img_for_save = joint_img_horizontal(batch_img, batch_output,batch_mask)
save_img(img_for_save, os.path.join(save_dir,"img_out_mask_%d.png"% i))

 

 

【补充】为什么有时候保存图片会失真?

在make_grid那里,你需要设置参数normalize = True。

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基于PyTorch的全景图像拼接代码示例: ```python import torch import numpy as np from PIL import Image # 定义模型 class PanoramaNet(torch.nn.Module): def __init__(self): super(PanoramaNet, self).__init__() self.conv1 = torch.nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1) self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1) self.conv3 = torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1) self.conv4 = torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1) self.conv5 = torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1) self.conv6 = torch.nn.Conv2d(512, 1024, kernel_size=3, stride=1, padding=1) self.upconv1 = torch.nn.ConvTranspose2d(1024, 512, kernel_size=2, stride=2) self.upconv2 = torch.nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2) self.upconv3 = torch.nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2) self.upconv4 = torch.nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2) self.upconv5 = torch.nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2) self.final_conv = torch.nn.Conv2d(32, 3, kernel_size=3, stride=1, padding=1) def forward(self, x): x = torch.nn.functional.relu(self.conv1(x)) x = torch.nn.functional.relu(self.conv2(x)) x = torch.nn.functional.relu(self.conv3(x)) x = torch.nn.functional.relu(self.conv4(x)) x = torch.nn.functional.relu(self.conv5(x)) x = torch.nn.functional.relu(self.conv6(x)) x = torch.nn.functional.relu(self.upconv1(x)) x = torch.nn.functional.relu(self.upconv2(x)) x = torch.nn.functional.relu(self.upconv3(x)) x = torch.nn.functional.relu(self.upconv4(x)) x = torch.nn.functional.relu(self.upconv5(x)) x = self.final_conv(x) return x # 加载模型 model = PanoramaNet() model.load_state_dict(torch.load('panorama_model.pth')) # 加载输入图片 image1 = Image.open('image1.jpg') image2 = Image.open('image2.jpg') images = [image1, image2] # 将输入图片转换为PyTorch张量 images_tensors = [] for image in images: image_tensor = torch.tensor(np.array(image)) image_tensor = image_tensor.permute(2, 0, 1).float().unsqueeze(0) images_tensors.append(image_tensor) # 将输入张量传入模型,生成全景图像 with torch.no_grad(): output = model(torch.cat(images_tensors, dim=0)) output = output.squeeze().permute(1, 2, 0).numpy() # 将全景图像转换为PIL图像,保存结果 output_image = Image.fromarray((output * 255).astype(np.uint8)) output_image.save('panorama_image.jpg') ``` 该代码使用PyTorch实现了一个基于卷积神经网络的全景图像拼接模型,通过加载已经训练好的模型,输入两张图片,并生成拼接之后的全景图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值