首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何用100行神经网络代码为黑白图片着色

作者:Emil Wallnér

编译:Bot

左:1910年摄原图;右:PS手动着色后效果

编者按:如果给你一张黑白图片,你会怎样对它进行着色处理?相信大多数人会给出Photoshop这个答案。的确,技术发展到今日,PS这类美术工具大大简化了传统的绘画方式,给予用户更多便利,但如果涉及对图片着色,尤其是要求有各种环境、历史背景下的自然过渡,即便是有深厚美术功底的人,他们也要耗费数周乃至一个月的时间来层层渲染。那普通的开发者和想偷懒的设计师是不是和高效高质量着色没有缘分了呢?近日,博主Emil Wallnér授权论智向大家分享一篇初学者教程,只用100行代码就能帮你解决这个问题。

以下是由论智编译的原文:

测试中的一些失败案例,原始图像来自Unsplash

现在图像着色一般是在Photoshop中进行的,如果是对历史图片着色,工作人员可能需要进行长期调研,从政府、报社获得大量与当时历史背景相关的文字资料,并根据图片中的光线、场景进行长达一个月的手动劳作。光是一张脸,他们都需要添加多达20余层的粉色、绿色和蓝色,来使它恰到好处。

鉴于文章面对的是初学者,如果你对一些专业术语还没有深刻的了解,你可以先阅读我之前的两篇博文:深度学习第一周和用代码编写深度学习历史。结合实践,我会在这篇文章中介绍我是如何建立着色神经网络的,它主要分为3个部分。

第一部分是分解核心逻辑。我将构建一个40行的神经网络作为着色机器人的α测版本,这一版不会涉及太多技巧,只作为熟悉语法的过程。

第二部分则是创建一个真正的β测神经网络。我将让它实现对一些从没见过的图片进行着色。

第三部分,也就是在最后的final版中,我会把神经网络和分类器结合起来。我使用的是已经在120万张图像上训练过的谷歌Inception Resnet V2,以及图片网站Unsplash上的肖像图(文末附公开数据集地址)。

核心逻辑

在本节中,我将概述渲染图像、颜色数值表示的基础知识和神经网络的主要逻辑。

黑白图像可以用像素网格来表示,每一个像素都有一个对应其亮度的值,数值0—225代表的正是从黑色到白色。

而彩色图像则可被分为3层:红色层、绿色层和蓝色层。这可能与我们的直观感受相悖,想象一下,如果把一幅白底色绿叶图分为3个调色通道,从直觉上说,我们可能会觉得它只存在于绿色层。

事实上,正如你所看到的,绿叶在三个调色通道中都存在,颜色层决定的不仅仅是颜色,还有亮度。

例如,如果你想调出白色,你就需要平均分配这三种颜色,在绿色中加入等量的红色和蓝色,使得绿色更亮。这种利用三原色的色光以不同的比例相加,以产生多种多样的色光的方法即是RGB模型,在彩色图像中,它使用红绿蓝三层来编码颜色和对比度:

就像黑白图片一样,彩色图像中的每一层都有一个0—225的值,值0表示它在这一层没有颜色,如果所有调色通道中的值都是0,那图像的像素就是黑色。

正如我们所知道的,神经网络会在输入和输出之间建立联系。为了更精确地实现我们的着色任务,神经网络需要找到将黑白图像于彩色图像连接起来的特征。

总之,我们正在寻找将灰度值网格连接到三色网格的方法。

f()是神经网络,[B&W]是我们的输入,[R],[G],[B]是我们的输出

Alpha版本

我们先从一个简单版本的神经网络开始,为一张普通女性面部图像着色。通过这种方式,你可以在添加功能的同时熟悉模型的核心语法。

只用40行代码,我们可以实现如下图的转换。其中右侧为原始彩色图像,左侧为黑白图像,中间的图片是由神经网络生成的。该网络在相同的图片上进行了训练和测试,之后我们会提到这一点。

摄影:Camila Cordeiro

色彩空间

首先,我们将用一种算法来改变调色通道,把它由RGB模型转为Lab模型。这是一种描述颜色显示方式的模型,其中L表示Luminosity,即亮度,a和b分别表示从洋红色至绿色的范围和从黄色至蓝色的范围。

正如你在下图中看到的,Lab模型编码的图像具有一个灰度涂层,并且将原来的3个颜色层分重新划分成了2个。这就意味着我们的最终测试版可以直接转换黑白图片,并且我们只需要对两种调色通道进行预测。

同时,科学研究证实,人眼中有高达94%的细胞决定我们看到的亮度,而作为颜色“传感器”的细胞只有剩下的6%。如上图所示,灰度图像比彩色图像锐利得多,这是我们将灰度图像保留下来的另一个原因。

从黑白到彩色

我们的最终想法是这样的:输入灰度层,之后预测Lab模型中a、b两个通道的颜色层。在下文中,我们用L表示输入的黑白图像,而输出则是Lab图像。

因为涉及把一个图层转换为两个图层,我们使用卷积filter(滤波器),这相当于3D眼镜使用的滤镜,它可以删除或提取原图中的部分信息,这在一定程度上决定了图像中可以被看到的的内容。有了它,神经网络能用一个filter创建图像,或将几个filter的内容组合在一起,形成一张新图。

对于卷积神经网络(CNN),每个filter都会自动调整以帮助实现预期效果,所以我们使用的方法是在a通道和b通道内堆叠数百个filter。

在介绍其他工作原理前,先让我们来运行一下代码。

在FloydHub上部署代码

如果你没有FloydHub,你可以先上官网去看一下它的两分钟安装教程,或者是我之前提到的的博客深度学习第一周,这是在云GPU上训练深度学习模型最好的、也是最简单的方法。

Alpha版

安装完FloydHub后,运行以下命令:

打开文件夹并启动FloydHub。

FloydHub web仪表盘会在浏览器中打开,之后系统会提示你创建一个FloydHub的新项目colornet。完成后,返回终端并运行相同的init命令。

之后,让我们开始干活:

这里先插播一则简要说明:

我已经在FloydHub上挂了一个公开数据集,放在目录中有

的data里。具体可以访问FloydHub查看。

我使用了Tensorboard--tensorboard

我使用了Jupyter Notebook模式--mode jupyter

如果还有GPU credits,你可以把GPU的flag--gpu添加到命令中,这大约能使模型运行速度加快50倍。

进入Jupyter笔记本,在FloydHub网站的工作标签下,点击Jupyter Notebook链接并导航到这个文件:

打开它,并对每个框Shift + Enter。

之后就可以逐渐增加epoch数值,感受神经网络的学习情况。

从epochs=1开始,我们把它慢慢增加到10、100、500、1000、3000。epoch数值表示神经网络学习的次数,而网络训练后的图像img_result.png可以在主文件夹中找到。

Alpha版代码:

用FloydHub命令运行神经网络:

技术说明

总而言之,输入是表示灰度的像素网格,它对应的输出是两个带有颜色数值的网格,在输入和输出间,我们用filter把它们连接在一起,这就形成一个卷积神经网络。

当我们训练网络时,我们使用了彩色图像,并把RGB色彩空间转换成了Lab色彩空间。如下图所示,黑白图层是我们的输入,两个彩色图层是输出。

在上图左侧,我们可以看到B&W输入、一些filter以及模型的预测。

第三幅图和第四幅图分别是相同间隔内预测值和实际值的情况,为了形成对比,我们在模型中使用了tanh激活函数,将间隔范围控制在-1到1之间。同时,由于Lab默认的色彩空间在-128到128之间,我们将它除以128,这样范围也就落入-1到1的区间内。这种“标准化”能使我们更简单直观地发现错误。

计算获得错误后,神经网络会通过更新filter减少误差,之后继续反复循环,直至错误率尽可能最低。

让我来解释其中的一些代码语法。

1.0/255表示我们使用的是24位RGB色彩空间,这意味着每个调色通道的值是0—255之间的数字,共有1670万种颜色组合。

由于人眼只能感知两百万至一千万种颜色,使用这么大的色彩空间并没有多大意义。

Lab的色彩空间与RGB相比范围不同,a、b两条通道的彩色光谱范围是-128到128,这就意味着通过将输出层中的所有值除以128,我们就能把它的范围控制在-1和1之间。

而这正好与我们的神经网络相匹配,它的返回值也在-1和1之间。

用函数rgb2lab()转换色彩空间后,我们选择灰度图层[ : , : , 0]——神经网络的输入;再用[ : , : , 1: ]把它分为两个颜色图层:绿—红、蓝—黄。

训练了神经网络后,我们得到最终预测,并将其转换成图片。

上述代码表示我们输入黑白图像后,神经网络得出了一些范围在-1到1之间的数值,通过乘以128,我们就能得到满足Lab色彩空间范围的真正数值。

最后,我们创建一个颜色数值为(0,0,0)黑色RGB画布,把测试图像中的灰度图层数值复制进去,再把Lab中的两个颜色层数值添加进去,这个形成的像素值数组就能转换成最终的输出图片。

Alpha版总结

阅读论文是一件颇具挑战性的事。我发现当我总结了某篇论文的核心要素后,就很容易忽视文章本身的。因此我在上下文中增加了许多细节描述;

从一个简单项目开始是成功的关键。我在网上找到的实现方法都要2000至1万行代码,这对于掌握这个问题的核心逻辑十分不利。但是一旦我找到了一个barebones版本,无论是阅读代码还是阅读论文,这些都变得很轻松;

探索公共项目。为了大致了解代码的内容,我在Github上参与了50—100个着色项目;

事情不总是按预期进行。刚开始的时候,模型只能生成黄色和红色,因为我使用了Relu激活函数,而它不能生成负数,也就是绿色和蓝色。最后我终于找到了解决办法——使用tanh激活函数并映射Y值;

理解>操作。我发现许多项目实现很快,很难参与合作,因此比起加快码代码的速度,我把重心放在了创新速度上。

明日预告:β测试版

如果你想了解Alpha版的缺点,我建议你按我说的建一个模型,并用数据集以外的图片试一试。你会发现它记住的只是训练集中的数据信息,并不能把经验延伸到从未见过的图像上。这正是我们要在β测试版种要做的:教神经网络推广所学经验。

和上一版一样,这一次作者用的还是自己创建的数据集,包括9500张训练图像和500张测试图像。以下是新版的着色效果。想了解详细信息,请锁定论智君!

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171211G0YIO700?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券