前言
PNG图像除了支持常见的灰度,真彩色,带alpha通道的灰度,带alpha通道的真彩色外,还支持8bit rgb/二值图像(通过索引color pallete来实现)。
在语义分割的训练样本准备过程中,需要生成8bit rgb彩色png图,如下所示。这个时候如果直接用opencv的imread和imwrite读写操作,只能生成8bit png灰度图或24bit的真彩图。
解决办法
既然opencv不能保存成8bit的rgb png,这里就推荐用PIL库中的Image模块来读写png。样例代码如下
import numpy as np
from PIL import Image # 使用PIL库中的Image模块
img = Image.open(photo_file)
gray_img = img.convert('L')
... ...
上面样例代码中的Convert()会根据传入参数的不同将图像变成不同的模式。PIL中有九种不同模式。分别为1,L, P, RGB,RGBA,CMYK,YCbCr,I,F。
这里重点介绍8bit png图像对应的模式参数。
模式‘1’为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。
模式‘L’为灰色图像它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转
换为“L”模式是按照下面的公式转换的:
L = R * 299/1000 + G * 587/1000+ B * 114/1000
模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。
结论
所以,如果想读写8bit rgb彩色png图像,就得用模型"P"。 具体示例代码如下所示。
import numpy as np
import PIL.Image as Image
src= Image.open("1.png")
mat = np.array(src)
dst = Image.fromarray(mat, 'P')
bin_colormap = [0,0,0] + [255,0,0]*254 # 彩色调色板,以具体情况来定
dst.putpalette(bin_colormap)
dst.save('new.png')
src.close()