Как сжать картинку python

Как сжать картинку python

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

Одна из самых удобных библиотек – Pillow, форк PIL, который позволяет открывать изображения разных форматов, задавать коэффициенты сжатия и сохранять файлы в оптимизированном виде. Например, при сохранении JPEG можно задать параметр quality от 1 до 95. Значение по умолчанию – 75, но в большинстве случаев можно опустить до 50–60 без заметной деградации изображения.

Для формата PNG, где используется сжатие без потерь, параметр optimize=True позволяет уменьшить размер файла примерно на 10–30% за счёт более эффективной упаковки данных. Дополнительно можно использовать ImageMagick через Python-обёртки или системные вызовы для более тонкой настройки.

Библиотека opencv-python даёт больше контроля при пакетной обработке. При сохранении JPEG можно указать флаг cv2.IMWRITE_JPEG_QUALITY, а для PNG – cv2.IMWRITE_PNG_COMPRESSION. Эти параметры полезны при автоматизированной обработке больших массивов изображений, где важна скорость и минимальный объём на выходе.

Если стоит задача максимального сжатия с потерей качества, библиотека imageio поддерживает работу с WebP – форматом, разработанным Google. Он показывает лучшие результаты по сравнению с JPEG и PNG в плане соотношения размер/качество. При экспорте в WebP можно управлять параметром quality и включать режим lossless для задач, где искажения недопустимы.

Как сжать JPEG без заметной потери качества с помощью Pillow

Для сжатия JPEG-изображений без выраженной деградации визуального качества можно использовать библиотеку Pillow. Главное – правильно настроить параметры сохранения.

  1. Установите библиотеку Pillow:
    pip install Pillow
  2. Откройте изображение и сохраните его с оптимизированными параметрами:
    
    from PIL import Image
    image = Image.open("input.jpg")
    image.save("output.jpg", format="JPEG", quality=85, optimize=True, progressive=True)
    

Пояснение параметров:

  • quality=85 – значение 85 обычно позволяет снизить размер файла без видимых искажений. Ниже 75 начинают появляться артефакты.
  • optimize=True – включает внутреннюю оптимизацию таблиц Хаффмана, что уменьшает итоговый размер.
  • progressive=True – создаёт прогрессивный JPEG, который загружается поэтапно. Это не влияет на размер, но повышает удобство загрузки в браузерах.

Рекомендуется избегать повторного сжатия уже сохранённого JPEG, так как каждое сохранение ухудшает качество. Если необходимо изменить размер изображения перед сжатием, используйте метод thumbnail() или resize() с фильтром Image.LANCZOS:


image = Image.open("input.jpg")
image = image.resize((1024, 768), Image.LANCZOS)
image.save("output.jpg", format="JPEG", quality=85, optimize=True, progressive=True)

Настройка степени сжатия PNG при сохранении в Pillow

Настройка степени сжатия PNG при сохранении в Pillow

Библиотека Pillow позволяет управлять степенью сжатия PNG через параметр compress_level при сохранении файла. Значение может быть от 0 до 9, где 0 – без сжатия, а 9 – максимальное сжатие.

Пример сохранения с минимальным и максимальным уровнем сжатия:

from PIL import Image
image = Image.open("input.png")
image.save("compressed_0.png", format="PNG", compress_level=0)
image.save("compressed_9.png", format="PNG", compress_level=9)

При compress_level=0 сохраняется скорость, но увеличивается размер файла. Уровень 6 считается сбалансированным: приемлемое сжатие без существенного увеличения времени. Уровень 9 заметно снижает размер, но замедляет процесс в 2–3 раза по сравнению с уровнем 6.

Параметр optimize=True может дополнительно уменьшить размер, но увеличивает время сохранения. Его имеет смысл применять при финальном сохранении:

image.save("compressed_opt.png", format="PNG", compress_level=6, optimize=True)

Для пакетной обработки приоритет – уровень 3–6 без optimize. Для единичных финальных файлов – 7–9 с optimize=True.

Сравнение размеров и качества изображений после сжатия в разных форматах

При сжатии одного и того же изображения в форматах JPEG, PNG и WebP с уровнем качества 75, получаются следующие результаты: JPEG – 240 КБ, PNG – 690 КБ, WebP – 170 КБ. При этом визуально WebP сохраняет детали на уровне JPEG, а PNG не даёт видимой разницы, несмотря на увеличенный размер.

JPEG подходит для фотографий с плавными градиентами. При сильном сжатии появляются артефакты, особенно на границах резких контрастов. PNG предпочтительнее для изображений с прозрачностью и резкими переходами, но нецелесообразен для фотографий из-за большого веса. WebP обеспечивает компромисс: при меньшем размере он сохраняет детали и поддерживает прозрачность.

Для сравнения сжимаем изображение 1920×1080 пикселей. При установке параметра качества на 50: JPEG – 150 КБ, WebP – 100 КБ, PNG остаётся на уровне 690 КБ, так как формат слабо поддаётся сжатию без потерь. При визуальной проверке JPEG теряет мелкие текстуры, WebP остаётся читаемым даже в тенях, PNG остаётся неизменным, но неоправданно тяжёлым.

Рекомендация: для веба использовать WebP с уровнем качества 70–80. JPEG применять только при необходимости совместимости, а PNG – для иконок, схем и изображений с прозрачностью, где важна точность.

Использование библиотеки OpenCV для сжатия изображений с перекодировкой

Использование библиотеки OpenCV для сжатия изображений с перекодировкой

OpenCV позволяет изменять формат изображения и управлять уровнем сжатия напрямую при сохранении. Это особенно полезно при перекодировке из форматов без сжатия (например, BMP) в форматы с поддержкой сжатия (например, JPEG или WebP).

Для перекодировки используется функция cv2.imwrite(), в которую можно передать параметры сжатия. Например, для JPEG ключ cv2.IMWRITE_JPEG_QUALITY позволяет задать степень сжатия от 0 до 100. Для WebP – cv2.IMWRITE_WEBP_QUALITY.

Пример кода для перекодировки изображения в JPEG с контролем качества:

import cv2
image = cv2.imread("input.png")
cv2.imwrite("output.jpg", image, [cv2.IMWRITE_JPEG_QUALITY, 75])

Для формата WebP:

cv2.imwrite("output.webp", image, [cv2.IMWRITE_WEBP_QUALITY, 80])

Если исходное изображение содержит альфа-канал, при сохранении в JPEG он будет отброшен. Для сохранения прозрачности следует использовать PNG или WebP. В случае PNG уровень сжатия задаётся параметром cv2.IMWRITE_PNG_COMPRESSION от 0 до 9 (где 9 – максимальное сжатие).

cv2.imwrite("output.png", image, [cv2.IMWRITE_PNG_COMPRESSION, 6])

OpenCV не сохраняет EXIF-данные, поэтому при работе с фотографиями, где это важно, библиотека может не подойти. Также OpenCV не выполняет прогрессивное кодирование JPEG, что может быть критично при работе с веб-ресурсами.

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

Как массово сжать изображения в папке и сохранить копии

Для пакетной обработки изображений в каталоге с сохранением копий подойдёт библиотека Pillow. Она позволяет изменять параметры сжатия JPEG и оптимизировать PNG без потери данных.

Установите Pillow, если она не установлена:

pip install Pillow

Пример скрипта для сжатия всех изображений в папке:

from PIL import Image
import os
source_folder = 'input_images'
output_folder = 'compressed_images'
os.makedirs(output_folder, exist_ok=True)
for filename in os.listdir(source_folder):
if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
input_path = os.path.join(source_folder, filename)
output_path = os.path.join(output_folder, filename)
with Image.open(input_path) as img:
if img.format == 'JPEG':
img.save(output_path, 'JPEG', quality=70, optimize=True)
elif img.format == 'PNG':
img.save(output_path, 'PNG', optimize=True)

Рекомендации:

  • quality=70 подходит для визуально незаметного сжатия JPEG.
  • optimize=True уменьшает размер без видимых потерь.
  • Сохраняйте результат в отдельной папке, чтобы не перезаписать оригиналы.
  • Для PNG нельзя задать quality, но optimize помогает снизить вес.

Скрипт можно расширить логированием, обработкой подкаталогов и фильтрацией по размеру файла.

Как измерить и сравнить потери качества после сжатия

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

Один из наиболее распространенных методов – это вычисление коэффициента пиксельной ошибки, такого как PSNR (Peak Signal-to-Noise Ratio). PSNR измеряет разницу между исходным и сжатым изображением. Чем выше значение PSNR, тем лучше сохраняется качество. Однако этот показатель не всегда дает полное представление о восприятии изображения человеком. Предел PSNR часто проявляется в случае сжатия с потерями, где высокие значения не всегда означают отсутствие видимых дефектов.

Другой важный показатель – это SSIM (Structural Similarity Index), который более точно оценивает восприятие изменений в изображении. SSIM учитывает изменения яркости, контраста и структуры, что делает его более подходящим для анализа потерь качества на уровне восприятия.

Чтобы провести качественное сравнение, можно использовать комбинацию этих метрик, например, сочетание PSNR и SSIM. PSNR даст количественную оценку, а SSIM – качественную, что позволит лучше понять, насколько сильно изменилось изображение после сжатия.

Также, для точной оценки потерь, стоит визуально анализировать изображение, используя методики сравнения с исходным. Это особенно важно для изображений с мелкими деталями, где даже незначительные изменения могут быть заметны глазу.

Еще одним полезным подходом является использование субъективных тестов качества, таких как шкала MOS (Mean Opinion Score). Этот метод предполагает оценку изображений группой людей, что позволяет получить объективные данные о восприятии изменений в изображении.

Вопрос-ответ:

Что такое сжатие изображений и зачем оно нужно в Python?

Сжатие изображений — это процесс уменьшения размера файла изображения без значительной потери качества. В Python сжатие часто используется для оптимизации веб-страниц, сокращения объема хранимых данных или уменьшения времени загрузки изображений. Существует два основных метода сжатия: без потерь, при котором качество изображения сохраняется, и с потерями, когда сжимаемый файл теряет часть деталей, но его размер значительно уменьшается.

Какие библиотеки Python используются для сжатия изображений?

Для сжатия изображений в Python чаще всего используют библиотеки Pillow и OpenCV. Pillow — это библиотека для работы с изображениями, которая позволяет открывать, изменять и сохранять изображения, а также сжимать их в различных форматах. OpenCV также подходит для обработки изображений и видео, и в нем есть функции для сжатия и изменения размеров изображений. В обоих случаях можно настроить уровень сжатия для достижения оптимального баланса между качеством и размером файла.

Ссылка на основную публикацию