Подтвердить что ты не робот

Как читать сырое изображение с помощью PIL?

У меня есть исходное изображение, где каждый пиксель соответствует целому числу без знака 16 бит. Я пытаюсь читать с помощью функции PIL Image.fromstring(), как в следующем коде:

if __name__ == "__main__":
    if (len(sys.argv) != 4):
        print 'Error: missing input argument'
        sys.exit()

    file = open(sys.argv[1], 'rb')
    rawData = file.read()
    file.close()

    imgSize = (int(sys.argv[2]), int(sys.argv[3]))

    # Use the PIL raw decoder to read the data.
    #   - the 'F;16' informs the raw decoder that we are reading a little endian, unsigned integer 16 bit data.
    img = Image.fromstring('L', imgSize, rawData, 'raw', 'F;16')

    im.save('out.png')

Документация PIL сообщает, что первым аргументом функции fromstring() является "режим". Однако, глядя на документацию и поиск в Google, я не смог найти подробностей о том, что на самом деле означает этот аргумент (я считаю, что это связано с цветовым пространством или что-то в этом роде). Кто-нибудь знает, где я могу найти более подробную ссылку о функции fromstring() и что означает аргумент mode?

4b9b3361

Ответ 1

Конкретная документация находится на http://effbot.org/imagingbook/concepts.htm:

Mode

Режим изображения определяет тип и глубину пикселя в изображении. текущая версия поддерживает следующие стандартные режимы:

  • 1 (1-битные пиксели, черно-белые, сохраненные с одним пикселем на каждый байт)
  • L (8-битные пиксели, черно-белые)
  • P (8-битные пиксели, отображаемые в любой другой режим с использованием цветовой палитры)
  • RGB (3х8-битные пиксели, истинный цвет)
  • RGBA (4x8-битные пиксели, истинный цвет с маской прозрачности)
  • CMYK (4x8-битные пиксели, цветоделение)
  • YCbCr (3х8-битные пиксели, цветной формат видео)
  • я (32-разрядные знаковые целочисленные пиксели)
  • F (32-разрядные пиксели с плавающей запятой)

PIL также обеспечивает ограниченную поддержку несколько специальных режимов, включая LA (L с альфой), RGBX (истинный цвет с padding) и RGBa (истинный цвет с предварительно умноженная альфа).

Ответ 2

Image.frombuffer(режим, размер, данные) = > изображение

(Новое в PIL 1.1.4). Создает память изображений из пиксельных данных в строке или буфере, используя стандартный "необработанный" декодер. В некоторых режимах память изображений будет совместно использовать память с исходным буфером (это означает, что изменения в исходном буфере объекта отражаются на изображении). Не все режимы могут обмениваться памятью; поддерживаемые режимы включают "L", "RGBX", "RGBA" и "CMYK". Для других режимов эта функция ведет себя как соответствующий вызов функции fromstring.

Я не уверен, что означает "L", но "RGBA" означает Red-Green-Blue-Alpha, поэтому я предполагаю, что RGBX эквивалентен RGB (изменить: при тестировании это не так)? CMYK - Cyan-Magenta-Yellow-Kelvin, который является другим типом цветового пространства. Конечно, я предполагаю, что, если вы знаете о PIL, вы также знаете о цветовых пространствах. Если нет, Wikipedia имеет отличную статью.

Что касается того, что на самом деле означает (если этого недостаточно): значения пикселей будут закодированы по-разному для каждого цветового пространства. В регулярном RGB у вас есть 3 байта на пиксель - 0-254, 0-254, 0-254. Для Alpha вы добавляете еще один байт на каждый пиксель. Если вы декодируете RGB-изображение как RGBA, вы закончите чтение R-пикселя справа от первого пикселя в качестве альфы, что означает, что вы получите G-пиксель в качестве значения R. Это будет увеличено в зависимости от того, насколько велико ваш образ, но это действительно сделает ваши цвета неудобными. Точно так же попытка считывать изображение с кодировкой CMYK как RGB (или RGBA) сделает ваше изображение очень не похожим на него. Например, попробуйте сделать это с изображением:

i = Image.open('image.png')
imgSize = i.size
rawData = i.tostring()
img = Image.fromstring('L', imgSize, rawData)
img.save('lmode.png')
img = Image.fromstring('RGB', imgSize, rawData)
img.save('rgbmode.png')
img = Image.fromstring('RGBX', imgSize, rawData)
img.save('rgbxmode.jfif')
img = Image.fromstring('RGBA', imgSize, rawData)
img.save('rgbamode.png')
img = Image.fromstring('CMYK', imgSize, rawData)
img.save('rgbamode.tiff')

И вы увидите, что делают разные режимы - попробуйте использовать различные входные изображения: png с альфой, png без альфа, bmp, gif и jpeg. Это действительно забавный эксперимент.

Ответ 3

Если все остальное не удается, вы всегда можете прочитать исходный код. Для PIL загрузки здесь.

Вы точно не указали, в каком формате были пиксельные данные в 16-битных целых числах без знака, но я бы предположил, что это что-то вроде RRRRRGGGGGGBBBBBB (5-битный красный, 6-битный зеленый, 5-битовый синий) или RRRRRGGGGGBBBBBA (5-битный красный, 5-битный зеленый, 5-битный синий, 1-битный альфа или прозрачность). Я не видел поддержки этих форматов после очень быстрого просмотра некоторых источников, но не могу сказать точно так или иначе.

На той же веб-странице, где находятся загрузки PIL, они упоминают, что можно отправить вопросы в список рассылки Python Image SIG и предоставить для нее ссылку. Это может быть лучшим источником, чем просить здесь.

Надеюсь, что это поможет.

Ответ 4

Это старый вопрос, но это может помочь кому-то в будущем. Одна из проблем с исходным фрагментом кода заключается в том, что в Image.fromstring('L', imgSize, rawData, 'raw', 'F;16') часть F;16 работает в режиме 'F'.

Это работает для меня:

image = Image.fromstring('F', imgSize, rawData, 'raw', 'F;16')
image.convert('L').save('out.png')