强迫枕头产生一个图像与真彩色类型,而我只使用黑色和whi

2024-05-18 00:33:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用python3.6.6和Pillow==5.3.0生成图像。所有图像都有“JPEG”格式和“RGB”颜色模式。在

当我用颜色制作图像时,它将以Type: TrueColor(并且通道深度:红色:8位绿色:8位蓝色:8位)

当我只使用黑白时,它将以Type: Grayscale(并且通道深度:gray:8位)输出

因为我尝试使用只接受彩色图像的打印服务,所以我想尝试使黑白图像成为TrueColor图像,即使它们中没有任何其他(RGB)颜色。
我能简单地做这个吗?
或者,TrueColor图像是否意味着RGB值不能全部为0?在

我不知道我怎么能在枕头里做这个。我的首选方法是在Python代码中生成图像时强制执行此操作。在

另一种方法是使用工具转换图像(我使用的是ubuntu18.04,我使用的是ImageMagick和ffmpeg)。我尝试了下面的方法,但似乎没有任何效果。输出文件具有与原始文件相同的元数据。在

convert -type TrueColor original_file.jpeg converted_file.jpeg
convert -type TrueColor -depth 8 original_file.jpeg converted_file.jpeg

编辑示例(&E)

下面是Python代码,用相同的模式(RGB)创建两个图像。在

^{pr2}$

带有黑线的图像将有Type: Grayscale,而红线为Type: TrueColor。 注意,在这两种情况下,颜色空间都是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

所以我的问题是:我可以用枕头创建图像,这样,无论我使用什么颜色,它们总是以相同的type: TrueColor与3个通道?所以即使我在白色背景上画一条黑线。在

(注意:当我画一条默认宽度为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类型。 我对identify输出进行了区分,但是在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

Tags: 图像verbose颜色typelinebitrgbjpeg
3条回答

下面是一个使用ImageMagick将单通道灰度JPG图像强制为3通道颜色空间sRGB图像的示例。在

这里我创建了一个灰度渐变。然后使用Imagemagick identify-verbose,它显示为颜色空间的灰色。Exiftool确认为8位的1通道(颜色分量)。在

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
...


现在我使用-typetruecolor将灰度图像转换为颜色空间RGB。ImageMagick表示颜色空间RGB,exiftool显示它是3个通道(颜色分量),每个通道8位。在

^{pr2}$

我怀疑PIL通过读取或创建图像时使用的通道数来定义颜色空间。对不起,我对皮尔不太熟悉。但如果没有,那么你可以把它传给numpy,让它变成3个频道。然后把它带回皮尔。在

对我有用。在以下测试中:

  • BW-RGB.jpg是从Gimp导出的灰度等离子体图像(带有RGB通道)
  • BW-Grey.jpg是从Gimp导出的纯灰度(一个通道)中的同一个图像

IM的identify说:

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

如果我使用:

^{pr2}$

IM的identify说:

BW-Converted.jpg JPEG 400x400 400x400+0+0 8-bit sRGB 54.1KB 0.000u 0:00.000

所以结果确实是RGB。请注意,RGB和灰度文件的大小没有太大区别,这是预期的。彩色图像保存为三帧,黑白一帧和两帧色度图像,但对于灰度图像(R=G=B),这两幅色度图像只有一个统一的值,因此压缩效果非常好。在

PS:在Linux上,您可以使用file命令确认IM的identify报告:它报告一个灰度图像帧,三个彩色图像帧。在

更新答案

我一直在尝试这个,它似乎很难控制-至少对我来说!在

我试着在你的图像中添加一些随机的红、绿、蓝像素,但这似乎不会导致字体很快变为真彩色。在

然后,我试着对所有像素加上或减去少量随机噪声,并取得了一些进展,但图像在ImageMagick确认它是真彩色之前就变得“明显不愉快”。在JPEG编码器中抑制子采样和提高质量有一点帮助,但没有多大帮助。在

我发现我必须将N(噪声量)增加到9,然后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)) )

原始答案

我不确定我能理解。以下是我制作RGB图像时得到的结果:

^{pr2}$

现在我看看那些带有ImageMagick的图片,得到了我所期望的:

identify result*jpg

resultGRAY.jpg JPEG 640x480 640x480+0+0 8-bit Gray 256c 3932B 0.000u 0:00.000
resultRGB.jpg JPEG 640x480 640x480+0+0 8-bit sRGB 5427B 0.000u 0:00.000

你希望什么?请单击原始问题下的edit,并给出一个反例。在

相关问题 更多 >