Запись изображений после обработки: инструменты Python

Раздел: Компьютерное зрение -> основные операции с изображениями

Сохранение изображений в Python: основные методы

При работе с графическими данными на языке Python часто возникает необходимость записать результат обработки в файл. Существует несколько способов, каждый из которых подходит для определённых сценариев. Рассмотрим наиболее распространённые библиотеки и приёмы.

Основной и наиболее производительный способ: функция cv2.imwrite() из библиотеки OpenCV

OpenCV оптимизирован для работы с массивами NumPy и поддерживает множество форматов (PNG, JPEG, BMP, WebP, TIFF и другие). Функция imwrite() ожидает имя файла и массив данных. Возвращает True при успешной записи.


import cv2
import numpy as np

# Создание тестового изображения (жёлтый квадрат 200x200)
img = np.zeros((200, 200, 3), dtype=np.uint8)
img[:,:] = [0, 255, 255]  # BGR: жёлтый

# Сохранение в файл
success = cv2.imwrite('yellow_square.png', img)
if not success:
    print('Ошибка записи')
else:
    print('Файл yellow_square.png создан')

Python image save (сохранить изображение в python)

Параметры качества можно передать через список в третьем аргументе, например: cv2.imwrite('photo.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90]).

Типичные ошибки при использовании cv2.imwrite:

  • Если указанная директория не существует, файл не создаётся, а функция возвращает False. Следует предварительно проверить наличие папки или создать её с помощью os.makedirs().
  • Изображение должно быть 8-битным (dtype uint8) для большинства форматов. Если данные имеют тип float, их необходимо привести к диапазону 0-255 и преобразовать в uint8.
  • OpenCV использует порядок каналов BGR, тогда как многие библиотеки (например, PIL) используют RGB. При сохранении изображения, полученного из другого источника, может потребоваться конвертация cv2.cvtColor(img, cv2.COLOR_RGB2BGR).
  • Для форматов с альфа-каналом (PNG) массив должен иметь 4 канала (BGRA).

Как сохранить изображение с помощью библиотеки Pillow (PIL)?

Pillow предоставляет интуитивно понятный метод save() у объекта Image. Формат определяется по расширению файла. Поддерживаются все популярные растровые форматы.


from PIL import Image

# Создание синего изображения 150x150
img = Image.new('RGB', (150, 150), (0, 0, 255))
img.save('blue.png')
print('Изображение blue.png сохранено')

Дополнительные параметры передаются по ключу: img.save('photo.jpg', quality=80). Для PNG можно указать optimize=True для уменьшения размера.

Возможные проблемы:

  • Если файл заблокирован другой программой, возникнет ошибка PermissionError. Необходимо закрыть файл в других приложениях.
  • При сохранении изображений с альфа-каналом режим изображения должен быть 'RGBA' или 'PA', иначе прозрачность не сохранится.

Как задать уровень сжатия и качество при сохранении?

Наиболее часто настройка качества требуется для форматов JPEG и WebP. В Pillow используется параметр quality (0-100, по умолчанию 75). В OpenCV параметр передаётся через список флагов.


# Пример с PIL – сохранение JPEG с качеством 85
img_pil.save('compressed.jpg', quality=85)

# Пример с OpenCV – качество 90
cv2.imwrite('compressed.jpg', img_cv, [cv2.IMWRITE_JPEG_QUALITY, 90])

Для формата WebP доступны параметры lossless (True/False) и quality (0-100). В OpenCV: cv2.imwrite('img.webp', img_cv, [cv2.IMWRITE_WEBP_QUALITY, 80]).

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

  • Для JPEG качество ниже 50 приводит к заметным артефактам. Для фотографий рекомендуется 85-95.
  • Для PNG сжатие не теряет качество, но можно использовать optimize=True для уменьшения размера.

Как сохранить изображение с альфа-каналом (прозрачностью)?

Для сохранения прозрачности в PNG изображение должно содержать альфа-канал. В Pillow достаточно создать изображение в режиме 'RGBA' и сохранить как PNG. OpenCV требует массив BGRA (4 канала).


# Pillow: RGBA
img_rgba = Image.new('RGBA', (100, 100), (255, 0, 0, 127))  # красный полупрозрачный
img_rgba.save('semi_red.png')

# OpenCV: BGRA
img_bgra = np.zeros((100, 100, 4), dtype=np.uint8)
img_bgra[:,:,:3] = [0, 0, 255]  # BGR – синий
img_bgra[:,:,3] = 128          # альфа-канал
cv2.imwrite('semi_blue.png', img_bgra)

Внимание:

  • Если сохранить RGBA изображение из OpenCV без четвёртого канала, белая заливка заменит прозрачные области.
  • Некоторые форматы (JPEG) не поддерживают альфа-канал; при попытке сохранения PNG с прозрачностью в JPEG канал будет отброшен.

Как сохранить изображение в байтовый поток (BytesIO) без создания файла?

Это удобно для отправки изображения по сети или встраивания в HTML-код без записи на диск. Используется объект BytesIO из модуля io.


from PIL import Image
from io import BytesIO

img = Image.new('RGB', (50, 50), 'purple')
buffer = BytesIO()
img.save(buffer, format='PNG')
data = buffer.getvalue()
print(f'Размер буфера: {len(data)} байт')

Для OpenCV аналогично: ret, buf = cv2.imencode('.png', img_cv); data = buf.tobytes().

Ошибка:

  • При использовании imencode() необходимо указать расширение с точкой, например '.jpg'. Если расширение не поддерживается, функция вернёт False.

Как сохранить массив NumPy в виде сырых данных (без формата изображения)?

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


import numpy as np

data = np.random.randint(0, 256, (300, 400, 3), dtype=np.uint8)
np.save('raw_data.npy', data)
loaded = np.load('raw_data.npy')

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

Как сохранить изображение с метаданными (например, EXIF) в формате TIFF?

Библиотека tifffile позволяет указывать метаданные при записи TIFF-файлов. Это полезно для хранения дополнительной информации о снимке.


import tifffile
import numpy as np

img = np.ones((100, 100, 3), dtype=np.uint8) * 200
tifffile.imwrite('with_metadata.tif', img,
                 metadata={'ImageDescription': 'Тестовый снимок',
                           'Software': 'Python'})

Примечание:

  • Для установки tifffile используйте pip install tifffile.
  • Метаданные могут не читаться старыми программами, не поддерживающими TIFF-теги.

Расширенные примеры сохранения изображений

1. Пакетное сохранение нескольких изображений

Пример

import cv2
import numpy as np

# Генерируем список изображений
images = []
for i in range(5):
    img = np.zeros((100, 100, 3), dtype=np.uint8)
    img[:,:,0] = i * 50  # меняем синий канал
    images.append(img)

# Сохраняем каждое с уникальным именем
for idx, img in enumerate(images):
    filename = f'image_{idx}.jpg'
    cv2.imwrite(filename, img)
    print(f'{filename} сохранён')

Результат:

Созданы файлы image_0.jpg, image_1.jpg, ..., image_4.jpg с различными оттенками синего.

2. Сохранение после применения фильтра Гаусса

Пример

import cv2
import numpy as np

img = np.random.randint(0, 256, (200, 200, 3), dtype=np.uint8)
blurred = cv2.GaussianBlur(img, (5, 5), 1.5)
cv2.imwrite('blurred_example.png', blurred)
print('Размытое изображение сохранено')

Результат:

Файл blurred_example.png с размытым изображением.

3. Сохранение WebP с lossless сжатием

Пример

import cv2
import numpy as np

img = cv2.imread('input_image.jpg')  # предположим, что такой файл есть
if img is not None:
    cv2.imwrite('output_lossless.webp', img, [cv2.IMWRITE_WEBP_QUALITY, 100])
    print('WebP без потерь сохранён')
else:
    print('Изображение не найдено')

Результат:

Файл output_lossless.webp с максимально возможным качеством.

4. Сохранение в память и загрузка обратно

Пример

from PIL import Image
from io import BytesIO

img = Image.new('RGB', (64, 64), 'green')
buf = BytesIO()
img.save(buf, format='PNG')
buf.seek(0)
img_loaded = Image.open(buf)
print(f'Изображение загружено из памяти: {img_loaded.size}')

Результат:

Изображение загружено из памяти: (64, 64)

5. Сохранение с использованием scikit-image

Пример

from skimage import io, data

img = data.coffee()  # загружаем тестовое изображение
io.imsave('coffee_copy.png', img)
print('Файл coffee_copy.png создан')

Результат:

Файл coffee_copy.png с копией тестового изображения.

6. Сохранение изображения с плавающей точкой в формат HDR (EXR)

Пример

import imageio
import numpy as np

hdr_img = np.random.uniform(0, 1.0, (100, 100, 3)).astype(np.float32)
imageio.imwrite('hdr_output.exr', hdr_img)
print('HDR изображение сохранено')

Результат:

Файл hdr_output.exr, содержащий данные с плавающей точкой.

7. Сохранение grayscale изображения с применением цветовой карты (colormap)

Пример

import matplotlib.pyplot as plt
import numpy as np

gray = np.linspace(0, 1, 256).reshape(16, 16)
colored = plt.cm.viridis(gray)
plt.imsave('colormap_output.png', colored)
print('Изображение с цветовой картой сохранено')

Результат:

Файл colormap_output.png с псевдоцветами на основе карты viridis.

8. Сохранение анимированного GIF с помощью imageio

Пример

import imageio
import numpy as np

frames = []
for i in range(10):
    frame = np.zeros((50, 50, 3), dtype=np.uint8)
    frame[i*5:i*5+10, 20:30] = [255, 0, 0]
    frames.append(frame)
imageio.mimsave('animation.gif', frames, duration=0.2)
print('GIF анимация создана')

Результат:

Файл animation.gif, содержащий 10 кадров с движущимся красным прямоугольником.

сохранить изображение в Python - comments

En
Python image save (python)