在 geoTIFF 中获取所有唯一颜色时,如何知道 PIL 指的是啥颜色?

Posted

技术标签:

【中文标题】在 geoTIFF 中获取所有唯一颜色时,如何知道 PIL 指的是啥颜色?【英文标题】:How to know what colors PIL is referring to when getting all unique colors in a geoTIFF?在 geoTIFF 中获取所有唯一颜色时,如何知道 PIL 指的是什么颜色? 【发布时间】:2021-12-06 16:08:52 【问题描述】:

我有一堆要分析的 geoTIFF 图像。例如,下面是一个:

我想计算这张图片中有多少像素是蓝色的,有多少是白色的。我正在使用以下代码来获取此信息:

from PIL import Image
from collections import defaultdict

# open the image (fp is the filepath of the image)
im = Image.open(fp)
# the image is in 'P' mode

# convert to RGB?            
# im.convert('RGB')
            
by_color = defaultdict(int)
for pixel in im.getdata():
    by_color[pixel] += 1

im_col = Image.Image.getcolors(im)
print(im_col)
print(by_color)

这些图像处于“P”或调色板模式。无论我是否通过取消注释上面的那行代码将这些图像转换为“RGB”模式,我都会以这种格式得到以下输出(这个特定的输出是针对上面的示例图像):

[(777, 0), (196, 1), (378, 2), (1149, 3)]
defaultdict(<class 'int'>, 2: 378, 3: 1149, 1: 196, 0: 777)

所以,据我了解,0、1、2 和 3 代表唯一的像素颜色,而 777、196、378 和 1149 分别代表这些像素在图像中的次数(如果我加起来 777 + 196 + 378 + 1149 = 2500,这是有道理的,因为这是一张 50 像素 x 50 像素的图像)。

我的两个主要担忧是:

    为什么有四个值?根据图像,应该只有三个值:黑色背景、蓝色海洋和白色冰 - 是否有隐藏的颜色? 我如何知道 0、1、2 和 3 在托盘格式中代表什么颜色?我在某个网站上查找了一些颜色代码,我发现 0 表示 2,但 1 表示绿色,我知道这是不对的,所以我肯定在这里误解了一些东西。有没有办法使用 PIL 从图像中获取这个“颜色代码”?

提前致谢。

【问题讨论】:

请使用 Dropbox 或 Google Drive 等分享您的实际全尺寸图像。谢谢。 【参考方案1】:

你的图片有点奇怪,它有两对相同的调色板条目:

索引 1 == 索引 3,并且 索引 2 == 索引 4

如果您在终端中运行此命令,您可以使用 ImageMagick 看到:

magick identify -verbose 1QgAe.png

缩写输出

...
...
  Histogram:
    12431: (0,0,0) #000000 black
    6205: (0,0,254) #0000FE srgb(0,0,254)
    21364: (254,254,223) #FEFEDF srgb(254,254,223)
  Colormap entries: 256
  Colormap:
    0: (0,0,0,1) #000000FF black
    1: (254,254,223,1) #FEFEDFFF srgba(254,254,223,1)
    2: (0,0,254,1) #0000FEFF srgba(0,0,254,1)
    3: (254,254,223,1) #FEFEDFFF srgba(254,254,223,1)
    4: (0,0,254,1) #0000FEFF srgba(0,0,254,1)
...
...

srgb(254,254,223) 的 21,364 像素只是 3,126 和 18,238 的总和。


您也可以像这样使用pngcheck 看到它:

pngcheck -p 1QgAe.png 
File: 1QgAe.png (6135 bytes)
PLTE chunk: 256 palette entries
  0:  (  0,  0,  0) = (0x00,0x00,0x00)
  1:  (254,254,223) = (0xfe,0xfe,0xdf)
  2:  (  0,  0,254) = (0x00,0x00,0xfe)
  3:  (254,254,223) = (0xfe,0xfe,0xdf)
  4:  (  0,  0,254) = (0x00,0x00,0xfe)
  5:  (  0,  0,  0) = (0x00,0x00,0x00)
  ...
  ...

如果你想用 PIL 在 Python 中看到它,你可以使用这段代码,你会看到它是一样的:

#!/usr/bin/env python3

from PIL import Image

# Load image
im = Image.open('1QgAe.png')

if im.mode=='P':
    colours = im.getcolors()
    print(f'Colours: colours')

    palette = im.getpalette()
    for i in range(256):
        r = palette[3*i]
        g = palette[3*i+1]
        b = palette[3*i+2]
        print(f'palette[i] = rgb(r,g,b)')

样本输出

Colours: [(12431, 0), (3126, 1), (6205, 2), (18238, 3)]

palette[0] = rgb(0,0,0)
palette[1] = rgb(254,254,223)
palette[2] = rgb(0,0,254)
palette[3] = rgb(254,254,223)
palette[4] = rgb(0,0,254)
palette[5] = rgb(0,0,0)
palette[6] = rgb(0,0,0)

如果您对 Numpy 感到满意,您可以使用:

from PIL import Image
import numpy as np

# Load image
im = Image.open('1QgAe.png')
palette = np.array(im.getpalette()).reshape(256,3)
print(palette)

【讨论】:

以上是关于在 geoTIFF 中获取所有唯一颜色时,如何知道 PIL 指的是啥颜色?的主要内容,如果未能解决你的问题,请参考以下文章

什么是好的 GeoTiff 查看器? [关闭]

如何使用 lapply 在 R 中批量处理 geoTIFF

如何从imageview中的png获取特定颜色的所有像素

Swift:如何以编程方式获取iOS设备的唯一标识符?

将 GeoPDF 转换为 GeoTIFF

如何生成唯一的Android设备ID