编译:Bot

argb颜色对照rgb颜色_粉色rgb颜色代码_rgb颜色大全代码

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

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

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

今年早些时候,Amir Avni在社区介绍了一个能为历史黑白图片着色的机器人程序,通过深度学习神经网络,它能在短短几秒内就完成设计师长达一个月的手工劳动。我对Amir的网络十分着迷,于是下载了相关资源并做了一系列测试。

粉色rgb颜色代码_rgb颜色大全代码_argb颜色对照rgb颜色

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

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

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

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

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

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

核心逻辑

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

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

rgb颜色大全代码_argb颜色对照rgb颜色_粉色rgb颜色代码

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

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

rgb颜色大全代码_argb颜色对照rgb颜色_粉色rgb颜色代码

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

argb颜色对照rgb颜色_rgb颜色大全代码_粉色rgb颜色代码

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

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

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

argb颜色对照rgb颜色_粉色rgb颜色代码_rgb颜色大全代码

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

Alpha版本

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

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

argb颜色对照rgb颜色_粉色rgb颜色代码_rgb颜色大全代码

摄影:Camila Cordeiro

色彩空间

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

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

argb颜色对照rgb颜色_粉色rgb颜色代码_rgb颜色大全代码

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

从黑白到彩色

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

粉色rgb颜色代码_rgb颜色大全代码_argb颜色对照rgb颜色

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

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

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

在FloydHub上部署代码

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

Alpha版

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

  1. git clone https://github.com/emilwallner/Coloring-greyscale-images-in-Keras

打开文件夹并启动FloydHub。

  1. cd Coloring-greyscale-images-in-Keras/floydhub

  2. floyd init colornet

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

  1. floyd init colornet

之后,让我们开始干活:

  1. floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

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

  1. --dataemilwallner/datasets/colornet/2:data

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

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

  1. floydhub/Alpha version/working_floyd_pink_light_full.ipynb

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

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

  1. model.fit(x=X, y=Y, batch_size=1, epochs=1)

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

Alpha版代码:

  1. # Get images

  2. image = img_to_array(load_img('woman.png'))

  3. image = np.array(image, dtype=float)

  4. # Import map images into the lab colorspace

  5. X = rgb2lab(1.0/255*image)[:,:,0]

  6. Y = rgb2lab(1.0/255*image)[:,:,1:]

  7. Y = Y / 128

  8. X = X.reshape(1, 400, 400, 1)

  9. Y = Y.reshape(1, 400, 400, 2)

  10. # Building the neural network

  11. model = Sequential()

  12. model.add(InputLayer(input_shape=(None, None, 1)))

  13. model.add(Conv2D(8, (3, 3), activation='relu', padding='same', strides=2))

  14. model.add(Conv2D(8, (3, 3), activation='relu', padding='same'))

  15. model.add(Conv2D(16, (3, 3), activation='relu', padding='same'))

  16. model.add(Conv2D(16, (3, 3), activation='relu', padding='same', strides=2))

  17. model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))

  18. model.add(Conv2D(32, (3, 3), activation='relu', padding='same', strides=2))

  19. model.add(UpSampling2D((2, 2)))

  20. model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))

  21. model.add(UpSampling2D((2, 2)))

  22. model.add(Conv2D(16, (3, 3), activation='relu', padding='same'))

  23. model.add(UpSampling2D((2, 2)))

  24. model.add(Conv2D(2, (3, 3), activation='tanh', padding='same'))

  25. # Finish model

  26. model.compile(optimizer='rmsprop',loss='mse')

  27. #Train the neural network

  28. model.fit(x=X, y=Y, batch_size=1, epochs=3000)

  29. print(model.evaluate(X, Y, batch_size=1))

  30. # Output colorizations

  31. output = model.predict(X)

  32. output = output * 128

  33. canvas = np.zeros((400, 400, 3))

  34. canvas[:,:,0] = X[0][:,:,0]

  35. canvas[:,:,1:] = output[0]

  36. imsave("img_result.png", lab2rgb(canvas))

  37. imsave("img_gray_scale.png", rgb2gray(lab2rgb(canvas)))

用FloydHub命令运行神经网络:

  1. floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

技术说明

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

argb颜色对照rgb颜色_rgb颜色大全代码_粉色rgb颜色代码

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

粉色rgb颜色代码_rgb颜色大全代码_argb颜色对照rgb颜色

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

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

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

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

  1. X = rgb2lab(1.0/255*image)[:,:,0]

  2. Y = rgb2lab(1.0/255*image)[:,:,1:]

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

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

  1. Y = Y / 128

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

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

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

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

  1. output = model.predict(X)

  2. output = output * 128

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

  1. canvas = np.zeros((400, 400, 3))

  2. canvas[:,:,0] = X[0][:,:,0]

  3. canvas[:,:,1:] = output[0]

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

Alpha版总结

β测试版

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

和上一版一样,这一次我用的还是自己创建的数据集,包括9500张训练图像和500张测试图像。以下是新版的着色效果。

粉色rgb颜色代码_argb颜色对照rgb颜色_rgb颜色大全代码

特征提取器

在上一版中,我们的神经网络已经发现了黑白图像和彩色图像的对应方式。但是试想一下,如果你正在为一张黑白图片着色,但一次只能看到9个像素,无论怎么扭转方位观察,你真的能准确预测每个像素的真正颜色吗?

rgb颜色大全代码_粉色rgb颜色代码_argb颜色对照rgb颜色

我们可以举个例子,上图是介绍Alpha版时使用的女性肖像上的一处鼻孔边缘,你可以想象得到,在这种情况下要实现完美着色几乎是不可能的,所以我们需要把它分解为几个步骤。

首先,你需要在图像中发现一些简单图案,如对角线、全黑像素等。你要找出具有这些相同特征的像素并把它们归为一类。如果你有64个filter,那就意味着你能得到64张全新的图像。

rgb颜色大全代码_argb颜色对照rgb颜色_粉色rgb颜色代码

图像滤波过程

之后,如果你再次扫描图像,你会得到一些检测到的相同小图案,为了更好地理解它们,我们对它们的尺寸做多次减半处理。

粉色rgb颜色代码_rgb颜色大全代码_argb颜色对照rgb颜色

分三步缩小尺寸

当图案缩小到9个像素后,这时你还有一个3×3的低水平filter,通过它们的结合,你可以检测到一些更复杂的图案,如一个像素组合可能会形成一个半圆、一个小点或一条线。再一次,如果你从图片中反复提取相同的小图案,你就会得到128个全新的过滤图像,它们可能长这样:

rgb颜色大全代码_粉色rgb颜色代码_argb颜色对照rgb颜色

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击网站首页每天更新
站 长 微 信: aiwo51889