我使用Python 3.6.6和Pillow == 5.3.0生成图像。所有图像都具有“JPEG”格式和“RGB”颜色模式。
当我用颜色制作图像时,它会出现Type: TrueColor
(并且通道深度:红色:8位绿色:8位蓝色:8位)
当我只使用黑色和白色时,它会出现Type: Grayscale
(并且通道深度:灰色:8位)
由于我尝试使用仅接受我的彩色图像的打印服务,我想尝试使黑白图像成为TrueColor
图像,即使它们中没有任何其他(RGB)颜色。
我可以这么做吗?
或者TrueColor
图像是否意味着RGB值不能全部为0?
我不知道如何在Pillow中做到这一点。我首选的方法是在我的Python代码中生成图像时强制执行此操作。
另一种方法是使用工具转换图像(我在Ubuntu 18.04上,我使用ImageMagick和ffmpeg)。我尝试了以下,但它似乎没有做任何事情。输出文件与原始文件具有相同的元数据。
convert -type TrueColor original_file.jpeg converted_file.jpeg
convert -type TrueColor -depth 8 original_file.jpeg converted_file.jpeg
这是用于创建两个图像的Python代码,具有相同的模式(RGB)。
from PIL import Image, ImageDraw
white = (255, 255, 255)
black = (0, 0, 0)
red = (230, 25, 75)
def draw_line(file_name, line_color):
"""
Draw a 400x400 image with a white background and one
diagonal line of the given 'line_color'
"""
image = Image.new(mode='RGB', size=(400, 400), color=white)
draw = ImageDraw.Draw(image)
draw.line(xy=((100, 100), (300, 300)), fill=line_color, width=5)
image.save(fp=file_name, format='JPEG')
draw_line(file_name='black_line.jpeg', line_color=black
draw_line(file_name='red_line.jpeg', line_color=red)
带有黑色线条的图像将具有Type: Grayscale
,而带有红色线条的图像将具有Type: TrueColor
。请注意,ColorSpace在两种情况下都是sRGB,深度为8位。
identify black_line.jpeg
black_line.jpeg JPEG 400x400 400x400+0+0 8-bit sRGB 5.12KB 0.000u 0:00.000
identify -verbose black_line.jpeg
Type: Grayscale
Colorspace: sRGB
Depth: 8-bit
Channel depth:
gray: 8-bit
identify red_line.jpeg
red_line.jpeg JPEG 400x400 400x400+0+0 8-bit sRGB 5.26KB 0.000u 0:00.000
identify -verbose red_line.jpeg
Type: TrueColor
Colorspace: sRGB
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
所以我的问题是:我可以用Pillow创建图像,这样,无论我使用什么颜色,它们总是与3个通道一样出现type: TrueColor
?即使在我在白色背景上画一条黑线的情况下也是如此。
(注意:当我绘制一条默认宽度为1的红线时,它将有Type: Palette
而不是TrueColor
)
convert black_line.jpeg -type truecolor black_line_tc.jpeg
identify -verbose black_line_tc.jpeg |grep Type
Type: Grayscale
所以它不会将类型转换为TrueColor。我对识别输出进行了区分,但是关于channel_depth / colorspace / type等没有相关的区别,所以我不会发布输出。
identify -verbose black_line.jpeg > identity_black.txt
identify -verbose black_line_tc.jpeg > identity_black_tc.txt
diff identity_black.txt identity_black_tc.txt
适合我。在下面的测试中:
IM的BW-RGB.jpg
说:
BW-Grey.jpg
如果我使用:
identify
IM的BW-Grey.jpg JPEG 400x400 400x400+0+0 8-bit Gray 256c 48.2KB 0.010u 0:00.000
BW-RGB.jpg JPEG 400x400 400x400+0+0 8-bit sRGB 49.1KB 0.010u 0:00.019
说:
convert BW-Grey.jpg -type TrueColor BW-Converted.jpg
所以结果确实是RGB。请注意,RGB和灰度文件的大小差别不大,这是预期的。彩色图像保存为三帧,B&W一个和两个色度图像,但对于灰度图像(R = G = B),这两个色度图像具有一个单一的均匀值,因此压缩得非常好。
PS:在Linux上,您可以使用identify
命令确认IM的BW-Converted.jpg JPEG 400x400 400x400+0+0 8-bit sRGB 54.1KB 0.000u 0:00.000
报告:它报告灰度图像中的一个帧,以及三个彩色图像。
以下是使用ImageMagick将单通道灰度JPG图像强制为3通道色彩空间sRGB图像的示例。
在这里,我创建了一个灰度渐变。然后使用Imagemagick识别-verbose,它显示为颜色空间灰色。 Exiftool确认作为1通道(颜色分量)具有8位。
identify
现在我使用-type truecolor将灰度图像转换为colorspace RGB。 ImageMagick表示颜色空间RGB,exiftool表示它是3个通道(颜色分量),每个8位。
file
我怀疑PIL通过您在阅读或创建图像时使用的通道数来定义颜色空间。对不起,我对PIL并不熟悉。但如果没有,那么你可以将它传递给numpy以使其成为3个频道。然后把它带回PIL。
更新的答案
我一直在试验这个,看起来非常无法控制 - 至少对我来说!
我尝试在这里和那里添加一些随机的红色,绿色和蓝色单个像素,但它似乎不会导致类型很快改变为TrueColour。
然后我尝试向所有像素添加和减去少量随机噪声并取得一些进展,但在ImageMagick确认它是TrueColour之前,图像变得“明显不开心”。抑制JPEG编码器中的子采样并提高质量有一点帮助 - 但不是很多。
我发现在ImageMagick同意图像为TrueColour之前,我必须将convert -size 256x256 gradient: grad.jpg
identify -verbose grad.jpg
Image: grad.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: PseudoClass
Geometry: 256x256+0+0
Units: Undefined
Colorspace: Gray
Type: Grayscale
Base type: Undefined
Endianess: Undefined
Depth: 8-bit
Channel depth:
gray: 8-bit
...
exiftool -s -ee -g1 -u -n -D grad.jpg
...
- BitsPerSample : 8
- ColorComponents : 1
...
(噪音量)增加到9。你可能想试验一下,这里是代码:
convert grad.jpg -type truecolor grad_tc.jpg
Fredericks-Mac-mini:desktop fred$ identify -verbose grad_tc.jpg
Image: grad_tc.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 256x256+0+0
Units: Undefined
Colorspace: sRGB
Type: Grayscale
Base type: Undefined
Endianess: Undefined
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
...
exiftool -s -ee -g1 -u -n -D grad_tc.jpg
...
- BitsPerSample : 8
- ColorComponents : 3
...
原始答案
我不确定我理解。这是我制作RGB图像时得到的结果:
N
现在我看看那些使用ImageMagick并获得我期望的内容:
#!/usr/bin/env python3
from PIL import Image, ImageDraw
import numpy as np
def makeTrueColour(image):
"""
Force image to TrueColour by 'slightly distorting' greys.
Distortion means adding a tiny random amount of noise (0-N) to pixels that will not
"burn out" (i.e. exceed 255) as a result, and also subtracting a similar tiny
random amount of noise from pixels from pixels that will not underflow as a result.
If N=1, this means less than 0.4% error - hopefully imperceptible.
"""
N = 1
w, h = image.size
ni = np.array(image)
# Mask of pixels that will not exceed 255 by adding N
okpix = (ni <= (255 - N))
# Make additive noise in those pixels
noise = np.random.randint(0,N+1,size=(h,w,3),dtype=np.uint8) * okpix
ni += noise
# Mask of pixels big enough to subtract N
okpix = (ni >= N)
# Make subtractive noise in those pixels
noise = np.random.randint(0,N+1,size=(h,w,3),dtype=np.uint8) * okpix
ni -= noise
return(Image.fromarray(ni))
image = Image.new(mode='RGB', size=(400, 400), color=(255,255,255))
draw = ImageDraw.Draw(image)
draw.line(xy=((100, 100), (300, 300)), fill=(0,0,0), width=5)
tc = makeTrueColour(image)
tc.save('result.jpg',subsample=0,quality=95)
# This just counts the unique colours in "tc" - you don't need it
T = np.array(tc)
print(len(np.unique(T.reshape(-1, T.shape[2]), axis=0)) )
你还希望什么?请在原始问题下点击from PIL import Image
import numpy as np
# Make a fully black image
im = np.zeros([480,640,3], dtype=np.uint8)
# Save as RGB
Image.fromarray(im).save('resultRGB.jpg')
# Save as greyscale
Image.fromarray(grey).convert('L').save('resultGRAY.jpg')
并举一个反例。