#python #colors #python-imaging-library #rgb #color-palette
Вопрос:
У меня есть куча изображений геоТИФА, которые я пытаюсь проанализировать. Например, вот один из них ниже:
Я хотел бы подсчитать, сколько пикселей на этом изображении синие, а сколько белых. Я использую следующий код для получения этой информации:
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(lt;class 'int'gt;, {2: 378, 3: 1149, 1: 196, 0: 777})
Итак, насколько я понимаю, 0, 1, 2 и 3 представляют уникальные цвета пикселей, а соответствующие 777, 196, 378 и 1149 представляют количество раз, когда эти пиксели находятся на изображении (и если я сложу 777 196 378 1149 = 2500, это имеет смысл, так как это изображение размером 50 х 50 пикселей).
Мои две основные проблемы заключаются в следующем:
- Почему существует четыре значения? Согласно изображению, должно быть только три значения: черный фон, синий океан и белый лед — есть ли где-то скрытый цвет?
- Как я могу узнать, какие цвета представляют 0, 1, 2 и 3 в паллетированном формате? Я поискал какой-то цветовой код на каком-то веб-сайте и обнаружил, что 0 означает 2, но 1 означает зеленый, что, как я знаю, неправильно, поэтому я определенно что-то неправильно понимаю. Есть ли способ получить этот «цветовой код» из изображения с помощью PIL?
Заранее спасибо.
Комментарии:
1. Пожалуйста, поделитесь своим реальным полноразмерным изображением с помощью Dropbox, Google Диска или чего-то подобного. Спасибо.
Ответ №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) ... ...
21 364 пикселя, которые являются srgb(254 254 223), представляют собой всего лишь совокупные значения 3126 и 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) ... ...
Если вы хотите увидеть это в Python с PIL, вы можете использовать этот код, и вы увидите, что он такой же:
#!/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)