Как я могу сохранить изображение с помощью PIL?

119

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

from PIL import Image
import numpy as np

i = Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j = Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")

Я получаю следующую ошибку:

save_handler = SAVE[string.upper(format)] # unknown format
    KeyError: '.BMP'

Как я могу сохранить изображение с помощью Pythons PIL?

user1999274
источник

Ответы:

144

Ошибка, касающаяся расширения файла, была обработана, вы либо используете BMP(без точки), либо уже передаете выходное имя с расширением. Теперь, чтобы обработать ошибку, вам необходимо правильно изменить данные в частотной области для сохранения в виде целочисленного изображения, PILкоторое сообщает вам, что не принимает данные с плавающей запятой для сохранения в формате BMP.

Вот предложение (с другими небольшими изменениями, такими как использование fftshiftи numpy.arrayвместо numpy.asarray) для преобразования для правильной визуализации:

import sys
import numpy
from PIL import Image

img = Image.open(sys.argv[1]).convert('L')

im = numpy.array(img)
fft_mag = numpy.abs(numpy.fft.fftshift(numpy.fft.fft2(im)))

visual = numpy.log(fft_mag)
visual = (visual - visual.min()) / (visual.max() - visual.min())

result = Image.fromarray((visual * 255).astype(numpy.uint8))
result.save('out.bmp')
MMGP
источник
1
привет большое спасибо. теперь он работает отлично! Теперь все, что мне нужно сделать, это понять все шаги, но это будет неплохо. Большое спасибо за помощь
user1999274
@ user1999274 основное отличие заключается в использовании fft2вместо вместо, rfft2поскольку для дискретных данных я не вижу смысла использовать более позднее. Остальное чисто косметическое, т. Е. Вы не сможете правильно визуализировать преобразование Фурье, не применив к нему логарифмический коэффициент. Тогда нормализация должна упростить преобразование в диапазон [0, 255].
mmgp
1
visual = (visual - visual.min()) / (visual.max() - visual.min())будет по умолчанию, если visualнет дисперсии (маловероятно, но стоит уловить)
1
Я пытался использовать этот код для своей проблемы, но получаю простые черные изображения. Кто-нибудь знает об этом? stackoverflow.com/questions/24266000/…
user961627
32

Вы должны просто позволить PIL получить тип файла из расширения, то есть использовать:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
Wim
источник
1
Спасибо за вклад. однако, когда я пытаюсь разрешить функции сохранения получить тип файла, как вы предложили выше, я получаю следующую ошибку: IOError: не удается записать режим F как BMP. любой совет?
user1999274
1
Да, вам следует преобразовать массив в numpy.uint8dtype, а не в float.
wim
6

Попробуйте удалить .перед .bmp(он не соответствует BMPожидаемому). Как вы можете видеть из ошибки, save_handlerэто верхний регистр, который formatвы указали, а затем ищет совпадение SAVE. Однако соответствующий ключ в этом объекте BMP(вместо .BMP).

Я не очень разбираюсь в этом PIL, но при быстром поиске кажется, что это проблема с modeизображением. Изменение определения jна:

j = Image.fromarray(b, mode='RGB')

Казалось, у меня работает (однако обратите внимание, что я очень мало знаю PIL, поэтому я бы предложил использовать решение @ mmgp, поскольку он / она четко знает, что они делают :)). Для типов modeя использовал эту страницу - надеюсь, один из вариантов вам подойдет.

RocketDonkey
источник
Я попытался удалить .bmp в пользу BMP, но он все еще не работал. ошибка, которую я теперь получаю: IOError: не удается записать режим F как BMP. Я проверил страницы PIL на предмет документации и сказал, что нужно использовать .bmp, так что в целом я до сих пор не понимаю, почему он не работает.
user1999274
@ user1999274 Разместил обновление, которое, похоже, у меня сработало (извиняюсь за отсутствие деталей - собираю все вместе по мере продвижения :)).
RocketDonkey
@RocketDonkey, это было немного умнее, потому что преобразование результатов преобразования Фурье в цветовое пространство RGB даст бессмысленное изображение. Тот факт, что он больше не вызывает исключения, не означает, что результат правильный.
mmgp
@mmgp Согласен - вот почему я поставил +1 к твоему и надеюсь, что ОП его примет :)
RocketDonkey
4

Я знаю, что это старый, но я обнаружил, что (при использовании Pillow) открытие файла с помощью, open(fp, 'w')а затем сохранение файла будет работать. Например:

with open(fp, 'w') as f:
    result.save(f)

fp конечно, путь к файлу.

Нецко
источник
1
В документации Pillow сказано, что этот formatпараметр следует использовать, если используется файловый объект save. Разве в этом нет необходимости?
Роб Роуз
@RobRose во время тестирования, когда я опубликовал ответ, я не нашел в этом ничего необходимого. Однако теперь это может быть так. Если какое-либо тестирование, которое вы
проведете, подтвердит