Как сохранить фото в питоне
Перейти к содержимому

Как сохранить фото в питоне

  • автор:

Pillow — работа с картинками

Pillow — самая популярная библиотека для работы с изображениями в Python. С помощью неё картинки можно открывать, вращать, накладывать фильтры и даже работать с отдельными пикселями.

Обзор

Импортируется библиотека так:

from PIL import Image 

Pillow — улучшенная версия библиотеки PIL , поэтому импортируется она таким странным образом. В коде она будет называться PIL .

Далее попробуем что-нибудь сделать с картинкой:

from PIL import Image image = Image.open("example.jpg") rotated_image = image.rotate(45) rotated_image.save("rotated.jpg") 

Сначала открываем картинку с названием example.jpg и кладём её в переменную image . На следущей строке поворачиваем картинку на 45 градусов. Метод .rotate() не меняет картинку, а создаёт новую, поэтому положим её в переменную rotated_image . И в конце сохраняем повёрнутую картинку в новый файл rotated.jpg .

Атрибуты картинок

В Pillow есть новые типы данных: JpegImageFile , PngImageFile … Они позволяют хранить картинки прямо в переменных Python. У картинок есть несколько атрибутов, которые понадобятся вам в будущем:

  • format — формат данных картинки: jpeg , png …
  • mode — цветовая модель картинки: CMYK , RGB , L — для чёрно-белых изображений.
  • width — ширина картинки в пикселях.
  • height — высота картинки в пикселях.
  • size — размер картинки в пикселях. Возвращает tuple : (ширина, высота).

Как их извлечь:

from PIL import Image image = Image.open("example.jpg") print(image.format) # Выведет JPG print(image.mode) # Например, может вывести RGB 

Открыть картинку

Для открытия картинки используется функция Image.open() .

В качестве аргументов она принимает на вход путь до файла, который нужно открыть:

from PIL import Image image = Image.open("example.jpg") 

Сохранить картинку в файл

Для сохранения картинки есть метод .save() .

В качестве аргументов он принимает:

  • Путь до файла, в который сохранить картинку.
  • Именованный необязательный параметр format , в котором передаётся формат сохраняемой картинки.
from PIL import Image image = Image.open("example.jpg") image.save("new.jpg") image.save("another.jpg", format="JPEG") 

В качестве результата появится 2 копии картинки: new.jpg и another.jpg .

Перевести картинку в другую цветовую модель

О цветовой модели вы можете прочитать в разделе Атрибуты. Чтобы поменять цветовую модель картинки, нужно воспользоваться методом .convert() . Он принимает на вход именной аргумент mode :

from PIL import Image image = Image.open("example.jpg") print(image.mode) # Вывелось RGB cmyk_image = image.convert("CMYK") print(cmyk_image.mode) # Вывелось CMYK print(image.mode) # Вывелось RGB 

Заметим, что метод не меняет исходную картинку, а создаёт её копию с цветовой моделью CMYK . Поэтому мы положили её в отдельную переменную.

Обрезать картинку

За обрезание картинки отвечает метод .crop() . Он принимает на вход кортеж из 4 чисел: координат углов новой картинки. Координаты отсчитываются с левого верхнего угла картинки:

Координаты нужно передать в таком порядке: слева, сверху, справа, снизу. Например, вы хотите отрезать 10 пикселей слева и 15 сверху:

from PIL import Image image = Image.open("example.jpg") coordinates = (10, 15, image.width, image.height) cropped = image.crop(coordinates) # Отрежется 10 пикселей слева и 15 сверху 

Этот код отрезает 10 пикселей слева и 15 сверху. Самая правая координата — это и есть ширина картинки, а самая нижняя — высота, поэтому мы и использовали эти атрибуты картинки.

Разделить картинку на каналы

Картинки состоят из пикселей разных цветов. Каждый пиксель картинки в RGB состоит из 3 значений: сколько в нём красного, сколько зелёного и сколько синего. А в цветовой схеме CMYK из четырёх: голубой, пурпурный, жёлтый и чёрный. Все значения от 0 до 255. 0 — нет такого цвета, а 255 — его очень-очень много.

На самом деле картинки хранят не по пикселям, а по каналам. RGB картинка хранится как 3 картинки: в первой в каждом пикселе число от 0 до 255, показывающее, сколько в нём красного. Во второй то же, только с зелёным, а в третьем — с синим.

Получается 3 картинки. Но если взять какой-то цветовой канал отдельно от картинки, то она не будет знать, какой цвет ей показывать. У неё в каждом пикселе всего одно значение от 0 до 255. Поэтому она отображается как чёрно-белая. Если в пикселе хранится 0, то пиксель будет чёрный, а если 255 — белый. Чем больше число, тем светлее пиксель.

Метод .split() разбивает картинку на каналы. Работает так:

from PIL import Image image = Image.open("example.jpg") print(image.mode) # Вернуло CMYK, значит канала 4 cyan, magenta, yellow, key_color = image.split() # В переменные запишутся 4 чёрно-белые картинки. 

Собрать картинку из каналов

Pillow позволяет разделять картинку на каналы. Но так же позволяет и собирать её обратно. За это отвечает функция Image.merge() . Она принимает на вход 2 аргумента:

  • Цветовая модель будущей картинки
  • Кортеж из цветовых каналов. Если модель RGB, то первый канал будет покрашен в красный, второй в зелёный, третий в синий.
from PIL import Image image = Image.open("example.jpg") print(image.mode) # Вернуло CMYK, значит канала 4 cyan, magenta, yellow, key_color = image.split() # В переменные запишутся 4 чёрно-белые картинки. new_image = Image.merge("CMYK", (cyan, magenta, yellow, key_color)) 

new_image ничем не отличается от image , т.к. состоит из тех же каналов в том же порядке.

Покрасить цветовой канал

Pillow позволяет раскрашивать чёрно-белые картинки. За это отвечает функция ImageOps.colorize() .

Она принимает 3 аргумента: Картинка, какой цвет показывать вместо чёрного и какой вместо белого. Пример:

from PIL import Image, ImageOps image = Image.open("example.jpg") colorized = ImageOps.colorize(image, black ="red", white ="yellow") 

Код выше сделает из такой картинки:

Изменить размер картинки

Как работает thumbnail

Метод resize приводит картинку к желаемому размеру без сохранения пропорций. Картинка жмётся, становится некрасивой:

Метод thumbnail сохраняет пропорции:

Подробнее о thumbnail

С помощью метода .thumbnail() можно легко сделать миниатюру изображения. Миниатюра — уменьшенная версия картинки, с сохранением пропорций. На вход принимается кортеж с максимальными шириной и высотой. Метод .thumbnail() сам подберёт новые координаты так, чтобы картинка поместилась в заданную область. Например, у вас есть картинка 800×1200 и вы хотите поместить её в рамку 1200×600, то результат метода будет 400×600, т.к. 400×600 как раз помещается в 1200×600:

from PIL import Image image = Image.open("example.jpg") print(image.size) # Вывелось (800, 1200) image.thumbnail((1200, 600)) # Картинка теперь размера 400 на 600 print(image.size) # Вывелось (400, 600) 

Наложить картинки друг на друга

Функция Image.blend() создаёт новую картинку, накладывая одно изображение поверх другого. Для работы ему необходимы три аргумента:

  • Первая картинка.
  • Вторая картинка, того же размера, что и первая.
  • Коэффициент прозрачности.

Если прозрачность равна 0.5, то картинки смешаются в равных долях. Если коэффициент равен 1.0, то первая картинка станет полностью прозрачной и останется только вторая. Если 0.0, то наоборот. Прозрачность задаётся дробным числом через точку.

from PIL import Image image1 = Image.open("image1.jpg") image2 = Image.open("image2.jpg") image3 = Image.blend(image1, image2, 0.5) # Получится картинка, сложенная из двух 

Наложить со смещением

Отдельного метода для этого нет, но получается за счёт комбинации .crop() и Image.blend().

  1. Выберите картинку для эффекта. У нас это картинка wave.png с шириной в 1000 пикселей.
  2. Отрежьте от неё 200 пикселей слева. Получится wave_left.png шириной 800 пикселей.
  3. Возьмите исходную картинку wave.png и отрежьте от неё по 100 пикселей с обоих сторон: слева и справа. Получится wave_middle.png тоже шириной в 800 пикселей.
  4. Наложите wave_left.png на wave_middle.png с помощью Image.blend()
  5. Сохраните в файл то, что получилось. Это картинка смещённая влево.

Попробуйте бесплатные уроки по Python

Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

Четыре метода загрузки изображений с веб-сайта с помощью Python

Недавно пришлось по работе написать простенький парсер на питоне, который бы скачивал с сайта изображения (по идее тот же самый парсер может качать не только изображения, но и файлы других форматов) и сохранял их на диске. Всего я нашел в интернете четыре метода. В этой статье я их решил собрать все вместе.

1-ый метод

Первый метод использует модуль urllib (или же urllib2). Пусть имеется ссылка на некое изображение img. Метод выглядит следующим образом:

import urllib resource = urllib.urlopen(img) out = open(". \img.jpg", 'wb') out.write(resource.read()) out.close() 

Здесь нужно обратить внимание, что режим записи для изображений — ‘wb’ (бинарный), а не просто ‘w’.

2-ой метод

Второй метод использует тот же самый urllib. В дальнейшем будет показано, что этот метод чуть медленнее первого (отрицательный оттенок фактора скорости парсинга неоднозначен), но достоин внимания из-за своей краткости:

import urllib urllib.urlretrieve(img, ". \img.jpg") 

Притом стоит заметить, что функция urlretrieve в библиотеке urllib2 по неизвестным мне причинам (может кто подскажет по каким) отсутствует.

3-ий метод

Третий метод использует модуль requests. Метод имеет одинаковый порядок скорости выгрузки картинок с первыми двумя методами:

import requests p = requests.get(img) out = open(". \img.jpg", "wb") out.write(p.content) out.close() 

При этом при работе с веб в питоне рекомендуется использовать именно requests вместо семейств urllib и httplib из-за его краткости и удобства обращения с ним.

4-ый метод

Четвертый метод по скорости кардинально отличается от предыдущих методов (на целый порядок). Основан на использовании модуля httplib2. Выглядит следующим образом:

import httplib2 h = httplib2.Http('.cache') response, content = h.request(img) out = open('. \img.jpg', 'wb') out.write(content) out.close() 

Здесь явно используется кэширование. Без кэширования (h = httplib2.Http()) метод работает в 6-9 раза медленнее предыдущих аналогов.

Тестирование скорости проводилось на примере скачивания картинок с расширением *.jpg c сайта новостной ленты lenta.ru. Выбор картинок, подпадающих под этот критерий и измерение времени выполнения программы производились следующим образом:

import re, time, urllib2 url = "http://lenta.ru/" content = urllib2.urlopen(url).read() imgUrls = re.findall('img .*?src="https://habr.com/ru/articles/210238/(.*?)"', сontent) start = time.time() for img in imgUrls: if img.endswith(".jpg"): """реализация метода по загрузке изображения из url""" print time.time()-start 

Постоянно меняющиеся картинки на сайте не повлияли на чистоту измерений, поскольку методы отрабатывали друг за другом. Полученные результаты таковы:

Таблица сравнения скоростей методов

Метод 1, с Метод 2, с Метод 3, с Метод 4, с (без кэширования, с)
0.823 0.908 0.874 0.089 (7.625)

Данные представлены как результат усреднения результатов семи измерений.
Просьба к тем, кто имел дело с библиотекой Grab (и с другими), написать в комментариях аналогичный метод по скачиванию изображений с помощью этой и других библиотек.

  • питон и парсинг
  • изображения

Как сохранять фото на питон?

Нужен код для скачивания картинки с сайта (желательно,python)
есть определённая картинка,нужно её скачать.Подскажите пожалуйста код,например,для скачивания этой картинки https://pp.vk.me/c540104/c624218/v624218602/3321/u.

  • Вопрос задан более трёх лет назад
  • 30052 просмотра

Комментировать

Решения вопроса 8

На python 3 так можно:

import urllib.request url = "https://pp.vk.me/c540104/c624218/v624218602/3321/uYVa4FQv_q0.jpg" img = urllib.request.urlopen(url).read() out = open("img.jpg", "wb") out.write(img) out.close

Ответ написан более трёх лет назад

Нравится 12 1 комментарий

kostya__wolf

Константин Волков @kostya__wolf Автор вопроса

Большое спасибо за помощь!

борец с ветряными мельницами

И всего один человек использовал with, чудеса какие-то. Вот еще более общая реализация для python + requests:

import requests URL = 'https://pp.vk.me/c540104/c624218/v624218602/3321/uYVa4FQv_q0.jpg' r = requests.get(URL) with open(filename, 'wb') as fd: for chunk in r.iter_content(): fd.write(chunk)

Ответ написан более трёх лет назад

Нравится 12 2 комментария

Как скачать картинку с сайта на Python?

Как скачать картинку с сайта на Python?

Название файла парси из ссылки, принты на логгинг меняй. И логи на английском. Вынеси логику и клиентский код отдельно. Не вижу обработки ошибок для запросов. Библиотеку поменяй на httpx. Почему не class based, переписывай и сделай абстракцию для http клиента от которой и наследуйся. Если отдельный файл со скриптом то где if __name__ . ? Если запросов таких много будет, юзай асинхронку сразу лучше.

Так в целом по верхам прошлись, тегнешь после некст коммита, пока денаю пулл реквест.

P.s. Добавь ещё pillow, чекай что картинка валидная, пережми в jpeg и задай Макс разрешение по ширине и высоте чтобы большие картинки не сохранять в оригинале. Место на сторедже беречь надо, а не закидывать картинки по 50Мб.

Как много лишних действий, лишь бы на С++ не переписывать.

А если картинка не png, то и обойдемся

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *