如果手中仅有一张灰度图,能否给它上色呢?根据图像处理的相关知识可以知道,彩色图像转为灰度图像这个过程(伪彩色处理过程)是不可逆的,也就是说手中的这个灰度图不可能被某种算法无损的恢复为彩色图像,如下图:

然而,查阅资料发现相关的介绍非常少,仅仅找到一些伪彩色处理的基本概念,尽管opencv和matplotlib等都提供了伪彩色的功能,但是也很难找到其实现的细节。所以自己根据博客相关知识进行了整理,这种上色方式是为了给宇智波鼬的眼睛上色好看才选择的!

本次记录包含以下三个部分:

(1)R、G、B值与颜色的对应关系

(2)python实现上色方案

(3)上色结果分析

如何上色是完全按照个人喜好的,我选择的颜色值仅仅是一种参考。

1、R、G、B值与颜色的对应关系

我们知道,R、G、B值和颜色是具有对应关系的,比如下面展示的表格中【1】:当R=255,G=255,B=0时,颜色为“Yellow1”(第一行,三个值分别表示RGB,后面以# 开头表示16进制格式):

对于任何一种想要的颜色,都可以通过查阅【1】中提供的表选择到。所以上色过程就变为查表过程,通过给灰度图的不同位置或者不同灰度值选择不同的R、G和B值,就实现了上色。

2、python实现上色方案

按照我的理解,灰度图转为彩色图的核心在于如何给每个像素赋RGB值,如何赋值即对应一种规则。我根据操作发现按照亮度值(灰度值大小)区间的不同,来区分不同颜色是可行的。

通过查表,决定使用红色red、黑色black、粉色pink来给图像上色,对应的rgb值如下:

color_dict = {"black": [0, 0, 0],
"red": [238, 0, 0],
"pink": [255, 192, 203]}

决定颜色后,需要将灰度值分为三个区间(分几个区间表示自己想要几种颜色),分别为(0,15)、(15,140)以及(140,255),三个区间分别设置为black、red、pink,如下图:

上图横坐标表示像素值的大小,纵坐标表示对应的颜色值;python实现的代码如下:

def gray2rgb(gray, color_dict):
"""
convert gray image into RGB image
:param gray: single channel image with numpy type
:param color_dict: color map
:return: rgb image
"""
# 1:创建新图像容器
rgb_image = np.zeros(shape=(*gray.shape, 3))
# 2: 遍历每个像素点
for i in range(rgb_image.shape[0]):
for j in range(rgb_image.shape[1]):
# 3:对不同的灰度值选择不同的颜色
if gray[i, j] < 15:
rgb_image[i, j, :] = color_dict["black"]
elif 140 >= gray[i, j] >= 15:
rgb_image[i, j, :] = color_dict["red"]
else:
rgb_image[i, j, :] = color_dict["pink"]
return rgb_image.astype(np.uint8)

上色结果如下:

3、上色结果分析

是如何确定3个区间以及3个区间的端点值呢?

我是通过图像直方图确定的,通过统计0-255中每个值出现的次数,发现像素值普遍集中在0-120之间;尤其是像素值在0-15之间更是出现了峰值,这个区间肯定就是背景了!所以将这个范围的像素赋值为黑色;在15-140之间的像素分布比较均匀,对应的应该是眼球,设置为白色;对于大于140的区域,几乎没有多少像素点,随便选择一个无关紧要的颜色即可:

按照灰度值分层是很常见的操作,目前深度学习也有很多图像上色方面的研究,以后会做进一步研究。