强制枕头生成TrueColor类型的图像,而我只使用黑色和白色

问题描述 投票:1回答:3

我使用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

EDIT & Example

这是用于创建两个图像的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

尝试转换为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
python imagemagick python-imaging-library rgb image-formats
3个回答
1
投票

适合我。在下面的测试中:

  • qazxsw poi是从Gimp导出的灰度等离子图像(带有RGB通道)
  • qazxsw poi是从Gimp导出的纯灰度(一个通道)中的相同图像

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 报告:它报告灰度图像中的一个帧,以及三个彩色图像。


0
投票

以下是使用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。


0
投票

更新的答案

我一直在试验这个,看起来非常无法控制 - 至少对我来说!

我尝试在这里和那里添加一些随机的红色,绿色和蓝色单个像素,但它似乎不会导致类型很快改变为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') 并举一个反例。

© www.soinside.com 2019 - 2024. All rights reserved.