Python通过二维数组制作单通道8位的索引图片

1.问题引入

        在我们使用公共数据集进行训练时,我有时候会对数据集当中的标签图片的标签值进行修改,或者我想通过二维数组生成一个单通道的标签图片,对于这种的单通道图片,我们不能像生成RGB三通道图片那样直接生成,那么该怎么样生成呢?

2.索引图片

        索引图片,对于很多训练集的标签,都是使用的索引图片。索引图片又叫伪彩色图片,它是有颜色的,但是它只有一个通道,不像RGB图片有三个通道。它的颜色最多只有256种,可以通过使用颜色表对它的每个像素点上的数值(0~255)进行赋色。简单来说,索引图类似有颜色的灰度图(单通道图片),但它的颜色是要去赋值的或者系统自动生成。对于索引图片,将它转化成数组,可以得到一个二维数组。比如一张分辨率为600*600的索引图片,通过numpy将它转化成数组,可以生成一个600行、600列的二维数组,数组内的数值都在0~255之间,代表每个像素点上的数值。

from PIL import Image
import numpy as np

img = Image.open('0.png')
img_np = np.array(img)
print(img_np)

生成的结果:
[[220 220 220 ... 220 220 220]
 [220 220 220 ... 220 220 220]
 [220 220 220 ... 220 220 220]
 ...
 [220 220 220 ... 190 190 190]
 [220 220 220 ... 190 190 190]
 [220 220 220 ... 190 190 190]]

3.使用二维数组生成索引图片

        使用二维数组生成索引图片,首先得生成一个二维数组和一个颜色表。二维数组和颜色表都可以自己定义。这里,我接着上面的数组,对数组进行修改,生成新的图片,当然,也可以直接自己定义一个新的数组输出图片。

from PIL import Image
import numpy as np

img = Image.open('0.png')
img_np = np.array(img)
print(img_np)
for i in range(600):
    for j in range(600):
        if i < 100:
            img_np[i, j] = 0
        elif i < 200:
            img_np[i, j] = 1
        elif i < 300:
            img_np[i, j] = 2
        elif i < 400:
            img_np[i, j] = 3
        elif i < 500:
            img_np[i, j] = 4
        else:
            img_np[i, j] = 5
colors = [
    (255, 0, 0),  # 蓝色0
    (0, 255, 0),  # 绿色1
    (0, 0, 255),  # 红色2
    (255, 255, 0),  # 青色3
    (0, 255, 255),  # 黄色4
    (255, 0, 255),  # 深红色5
    (255, 192, 203),  # 粉红色6
    (0, 199, 140),  # 玉色7
    (128, 42, 42),  # 棕色8
    (255, 97, 0),  # 橙色9
    (0, 0, 0)  # 黑色 10
]
im = Image.fromarray(img_np)
im.convert('P')  # P代表索引图片
palette = np.array(colors).reshape(-1).tolist()
im.putpalette(palette)
im.save('0_out.png')

这样就可以输出新的索引图片:

 4.存在的问题:

        按照上面的代码,看上去一切正常,但是这里有一个很大的坑!本来读取的图片是单通道的图片,也就是位深度为8的图片。

        但是,生成图片的位深度却是4,按道理应该是单通道,8位的。

        在我多次尝试寻找问题到底出在那里,最后终于发现,原来问题出现在颜色表。可以从上面的颜色表看到,当时,我想我只需要给0~5赋色,就没有想着多增加几种颜色表,随便选了11种颜色填了上去。当把颜色表的颜色种类增加到17种时(17>2^4),图片的位深度就会变成8。同样的,要是颜色表只有4个,位深度会变成2。(因为我后面的6数值没用到,颜色时随便打的,如果0~255的数值都要用,而且要去区分,可以自行编写个函数生成颜色表)

colors = [
    (255, 0, 0),  # 红色0
    (0, 255, 0),  # 绿色1
    (0, 0, 255),  # 蓝色2
    (255, 255, 0),  # 黄色3
    (0, 255, 255),  # 青色4
    (255, 0, 255),  # 深红色5
    (255, 192, 203),  # 粉红色6
    (0, 199, 140),  # 玉色7
    (128, 42, 42),  # 棕色8
    (255, 97, 0),  # 橙色9
    (0, 0, 0),  # 黑色 10
    (0, 0, 0),  # 11
    (0, 0, 0),  # 12
    (0, 0, 0),  # 13
    (0, 0, 0),  # 14
    (0, 0, 0),  # 15
    (0, 0, 0)  # 16
]

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>