<acronym id='esma'><em id='esma'></em><td id='esma'><div id='esma'></div></td></acronym><address id='esma'><big id='esma'><big id='esma'></big><legend id='esma'></legend></big></address>

      <code id='esma'><strong id='esma'></strong></code>

    1. <i id='esma'></i>

      <ins id='esma'></ins>
    2. <fieldset id='esma'></fieldset>
        <span id='esma'></span>
          <i id='esma'><div id='esma'><ins id='esma'></ins></div></i>
          <dl id='esma'></dl>

        1. <tr id='esma'><strong id='esma'></strong><small id='esma'></small><button id='esma'></button><li id='esma'><noscript id='esma'><big id='esma'></big><dt id='esma'></dt></noscript></li></tr><ol id='esma'><table id='esma'><blockquote id='esma'><tbody id='esma'></tbody></blockquote></table></ol><u id='esma'></u><kbd id='esma'><kbd id='esma'></kbd></kbd>

          如何捕获一只彩色卓别林?黑白照片AI上色教程很友好|哈佛大触-教程

          • 时间:
          • 浏览:23855


          东京大学SGU申请团队 10年申请经验:https://qic.ac.cn/【微信/QQ:1119261】


          方栗子 编译自 GitHub

          量子位 出品 | 公众号 QbitAI

          老照片的手动着色魔法


          妈妈小时候已经有彩色照片了  ,不过那些照片 ,还是照相馆的人类手动上色的  。

          几十年之后  ,人们已经开始培育深度神经网络  ,来给老照片和老电影上色了 。

          来自哈佛大学的Luke Melas-Kyriazi (我叫他卢克吧) ,用自己训练的神经网络  ,把卓别林变成了彩色的卓别林 ,清新自然 。

          作为一只哈佛学霸  ,卢克还为钻研机器学习的小伙伴们写了一个基于PyTorch的教程  。

          虽然教程里的模型比给卓别林用的模型要简约一些 ,但效果也是不错了 。

          问题是什么  ?


          卢克说  ,给黑白照片上色这个问题的难点在于  ,它是多模态的——与一幅灰度图像对应的合理彩色图像  ,并不唯一  。

          这并不是正确示范


          传统模型需要输入许多额外信息  ,来辅助上色  。

          而深度神经网络 ,除了灰度图像之外  ,不需要任何额外输入  ,就可以完成上色 。

          在彩色图像里  ,每个像素包含三个值  ,即亮度饱和度以及色调  。

          而灰度图像  ,并无饱和度色调可言  ,只有亮度一个值  。

          所以  ,模型要用一组数据  ,生成另外两足数据  。换句话说  ,以灰度图像为起点  ,推断出对应的彩色图像 。

          为了简单  ,这里只做了256 x 256像素的图像上色  。输出的数据量则是256 x 256 x 2 。

          关于颜色表示  ,卢克用的是LAB色彩空间  ,它跟RGB系统包含的信息是一样的  。

          但对程序猿来说  ,前者比较方便把亮度和其他两项分离开来  。

          数据也不难获得  ,卢克用了MIT Places数据集 ,中的一部分 。内容就是校园里的一些地标和风景  。然后转换成黑白图像  ,就可以了  。以下为数据搬运代码——
          1# Download and unzip (2.2GB)2!wget http://data.csail.mit.edu/places/places205/testSetPlaces205_resize.tar.gz3!tar -xzf testSetPlaces205_resize.tar.gz
          1# Move data into training and validation directories2import os3os.makedirs('images/train/class/', exist_ok=True) # 40,000 images4os.makedirs('images/val/class/', exist_ok=True) # 1,000 images5for i, file in enumerate(os.listdir('testSet_resize')):6 if i < 1000: # first 1000 will be val7 os.rename('testSet_resize/' + file, 'images/val/class/' + file)8 else: # others will be val9 os.rename('testSet_resize/' + file, 'images/train/class/' + file)
          1# Make sure the images are there2from IPython.display import Image, display3display(Image(filename='images/val/class/84b3ccd8209a4db1835988d28adfed4c.jpg'))

          好用的工具有哪些  ?


          搭建模型和训练模型是在PyTorch里完成的  。

          还用了torchvishion ,这是一套在PyTorch上处理图像和视频的工具 。

          另外 ,scikit-learn能完成图片在RGB和LAB色彩空间之间的转换  。
          1# Download and import libraries2!pip install torch torchvision matplotlib numpy scikit-image pillow==4.1.1
          1# For plotting2import numpy as np3import matplotlib.pyplot as plt4%matplotlib inline5# For conversion6from skimage.color import lab2rgb, rgb2lab, rgb2gray7from skimage import io8# For everything9import torch10import torch.nn as nn11import torch.nn.functional as F12# For our model13import torchvision.models as models14from torchvision import datasets, transforms15# For utilities16import os, shutil, time
          1# Check if GPU is available2use_gpu = torch.cuda.is_available()

          模型长什么样 ?


          神经网络里面  ,第一部分是几层用来提取图像特征;第二部分是一些反卷积层 (Deconvolutional Layers)  ,用来给那些特征增加分辨率  。

          具体来说  ,第一部分用的是ResNet-18 ,这是一个图像分类网络  ,有18层  ,以及一些残差连接 (Residual Connections)  。

          给第一层做些修改 ,它就可以接受灰度图像输入了  。然后把第6层之后的都去掉 。

          然后  ,用代码来定义一下这个模型  。

          从神经网络的第二部分 (就是那些上采样层) 开始  。
           1class ColorizationNet(nn.Module):2 def __init__(self, input_size=128):3 super(ColorizationNet, self).__init__()4 MIDLEVEL_FEATURE_SIZE = 12856 ## First half: ResNet7 resnet = models.resnet18(num_classes=365)8 # Change first conv layer to accept single-channel (grayscale) input9 resnet.conv1.weight = nn.Parameter(resnet.conv1.weight.sum(dim=1).unsqueeze(1))10 # Extract midlevel features from ResNet-gray11 self.midlevel_resnet = nn.Sequential(*list(resnet.children())[0:6])1213 ## Second half: Upsampling14 self.upsample = nn.Sequential( 15 nn.Conv2d(MIDLEVEL_FEATURE_SIZE, 128, kernel_size=3, stride=1, padding=1),16 nn.BatchNorm2d(128),17 nn.ReLU(),18 nn.Upsample(scale_factor=2),19 nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1),20 nn.BatchNorm2d(64),21 nn.ReLU(),22 nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),23 nn.BatchNorm2d(64),24 nn.ReLU(),25 nn.Upsample(scale_factor=2),26 nn.Conv2d(64, 32, kernel_size=3, stride=1, padding=1),27 nn.BatchNorm2d(32),28 nn.ReLU(),29 nn.Conv2d(32, 2, kernel_size=3, stride=1, padding=1),30 nn.Upsample(scale_factor=2)31 )3233 def forward(self, input):3435 # Pass input through ResNet-gray to extract features36 midlevel_features = self.midlevel_resnet(input)3738 # Upsample to get colors39 output = self.upsample(midlevel_features)40 return output

          下一步 ,创建模型吧 。
          1model = ColorizationNet()

          它是怎么训练的 ?


          预测每个像素的色值  ,用的是回归 (Regression) 的方法 。

          损失函数 (Loss Function)

          所以  ,用了一个均方误差 (MSE) 损失函数——让预测的色值与参考标准 (Ground Truth) 之间的距离平方最小化  。
          1criterion = nn.MSELoss()

          优化损失函数

          这里是用Adam Optimizer优化的  。
          1optimizer = torch.optim.Adam(model.parameters(), lr=1e-2, weight_decay=0.0)

          加载数据

          用torchtext加载数据  。首先定义一个专属的数据加载器 (DataLoader) ,来完成RGB到LAB空间的转换  。
           1class GrayscaleImageFolder(datasets.ImageFolder):2 '''Custom images folder, which converts images to grayscale before loading'''3 def __getitem__(self, index):4 path, target = self.imgs[index]5 img = self.loader(path)6 if self.transform is not None:7 img_original = self.transform(img)8 img_original = np.asarray(img_original)9 img_lab = rgb2lab(img_original)10 img_lab = (img_lab + 128) / 25511 img_ab = img_lab[:, :, 1:3]12 img_ab = torch.from_numpy(img_ab.transpose((2, 0, 1))).float()13 img_original = rgb2gray(img_original)14 img