PIL, numpy и matplotlib создают сюжет, который сильно отличается от исходного изображения - PullRequest
1 голос
/ 02 февраля 2020

Я пытаюсь построить несколько изображений, используя код ниже:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
if __name__ == "__main__":
    image2 = Image.open("Test Images/i3.png")
    image2 = np.asarray(image2)
    plt.imshow(image2, cmap="gray")
    plt.tight_layout()
    plt.show()

Но он отображает что-то отличное от того, что я вижу в программе просмотра изображений:

enter image description here

enter image description here

Почему это происходит?

Исходное изображение:

enter image description here

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

Это потому, что PNG имеет палитру, поэтому данные пикселей являются индексами палитры. np.asarray принимает необработанные данные пикселей, палитра не учитывается.

Используйте .get_palette() is not None на объекте изображения PIL, чтобы определить, имеет ли изображение палитра и .convert() для преобразования данных пикселей в "реальные" цвета.


Это часть необработанных данных, чтобы вы могли понять, как они выглядят , Он включает в себя угол столицы «C» в надписи:

raw data

Странная вещь, которая бросается в глаза, это то, что черный цвет 0 (ожидаемо), белый почему-то 1 (а не ожидаемый 255), а другие цвета выше, но все еще малы, самое высокое значение - 20. Что намекает на то, что это палитра.

Когда вы .imshow эти данные, нормализуется до [0,1], отображая эти 20 точек по порядку, чтобы точки были одинаково отделены друг от друга. другие на спектре Colormap.

png-parser могут отображать данные палитры:

$ png-parser -d amdNt.png
<...>
Filename: amdNt.png | Size: 2925

(0)
IHDR:
Data size : 13
 - Width : 225
 - Height : 225
 - Bit depth : 8
 - Color type : Code = 3 ; Depth Allow = [1, 2, 4, 8] ; Each pixel is a palette index; a PLTE chunk must appear.
 - Compression method : 0
 - Filter method : 0
 - Interlace method : 0


(1)
PLTE:
Data size : 69
b'\x00\x00\x00\xff\xff\xff\xfe\xfe\xfe\x01\x01\x01\xfd\xfd\xfd\xb4\xb4\xb4\xb2\xb2\xb2\xb6\xb6\xb6\xaf\xaf\xaf\x05\x05\x05\xfa\xfa\xfa\x10\x10\x10\xbb\xbb\xbb\x16\x16\x16\xb8\xb8\xb8\x0e\x0e\x0e\xf5\xf5\xf5\xaa\xaa\xaa\xc0\xc0\xc0\xf0\xf0\xf0\x19\x19\x19\xc4\xc4\xc4\xa6\xa6\xa6'
<...>

, а также саму палитру:

palette

0 голосов
/ 02 февраля 2020

Взгляните здесь , чтобы понять изображения на поддонах (или проиндексированные).

Краткий рассказ:

  • , если хотите и ожидайте изображение в градациях серого с PIL, тогда вы всегда должны использовать:

    im = Image.open("filename").convert('L')

в противном случае вы можете получить изображение палитры.

  • если вы хотите и ожидаете RGB-изображение с PIL, вам следует использовать:

    im = Image.open("filename").convert('RGB')

Если вы этого не сделаете, PIL может дать вам изображение палитры.

Кроме того, если вы открываете изображения с помощью PIL, обычно рекомендуется отображать их с помощью PIL и сохранять их с помощью PIL, в противном случае вы можете столкнуться с проблемами RGB / BGR. порядок, если вы открываете с помощью PIL и отображаете с помощью OpenCV, или с помощью цветовых карт, если вы отображаете их с помощью matplotlib. Я не говорю, что вы не можете взаимодействовать, я просто говорю, что несколько сложнее смешивать библиотеки без проблем упорядочения каналов и диапазонов значений.

...