Получение габаритов картинок на Python
Способы получения размеров изображения в Python
Как получить размеры изображения с помощью OpenCV?
OpenCV (cv2) является стандартной библиотекой для задач компьютерного зрения. Для получения размеров изображения используется функция cv2.imread(), которая возвращает массив numpy. Атрибут shape этого массива содержит кортеж (высота, ширина, количество каналов).
import cv2
img = cv2.imread('image.jpg')
if img is not None:
height, width, channels = img.shape
print(f'Ширина: {width}, Высота: {height}, Каналы: {channels}')
else:
print('Ошибка: изображение не загружено')Python работа с изображениями библиотеки (работа с изображениями в python с помощью библиотек)
Важно: cv2.imread возвращает None, если файл не найден или не может быть прочитан (неподдерживаемый формат, повреждённый файл). Перед обращением к shape следует проверять результат.
Типичные проблемы:
- Файл не существует или указан неверный путь. Решение: использовать абсолютный путь или проверить наличие файла через os.path.exists().
- Формат изображения не поддерживается (например, .webp в старой версии OpenCV). Решение: обновить OpenCV или конвертировать изображение.
- Изображение загружено в оттенках серого (одноканальное). В этом случае img.shape вернёт только (height, width). Необходимо проверять длину кортежа.
Как узнать размер изображения с помощью библиотеки Pillow (PIL)?
Pillow (PIL) предоставляет более высокоуровневый интерфейс. Метод Image.open() возвращает объект Image, у которого есть атрибут size в виде кортежа (ширина, высота).
from PIL import Image
try:
with Image.open('image.jpg') as img:
width, height = img.size
print(f'Размеры: {width}x{height}')
except Exception as e:
print(f'Ошибка: {e}')Python pillow image (библиотека pillow для изображений)
PIL позволяет читать многие форматы без установки дополнительных кодеков. Однако при загрузке повреждённого файла может возникнуть исключение, которое обязательно обрабатывать.
Возможные ошибки:
- Файл не найден – FileNotFoundError.
- Файл не является изображением – UnidentifiedImageError.
- Недостаточно памяти для загрузки большого изображения. Решение: использовать метод Image.open() с контекстным менеджером и не удерживать объект дольше необходимого.
Как получить размеры с помощью библиотеки imageio?
Библиотека imageio поддерживает множество форматов и может возвращать массив numpy. Для получения размеров используется imageio.imread() и shape.
import imageio
try:
img = imageio.imread('image.jpg')
height, width, channels = img.shape if img.ndim == 3 else (img.shape[0], img.shape[1], 1)
print(f'Размеры: {width}x{height}, каналы: {channels}')
except Exception as e:
print(f'Ошибка: {e}')
Python размер изображения (получение размеров изображения в python)
Проблема: imageio.imread() загружает всё изображение в память. Для больших изображений может быть неэффективно.
Как определить размер без загрузки всего изображения (чтение заголовка)?
Для эффективного получения размеров без полной загрузки можно анализировать заголовок файла. Например, для JPEG читаются маркеры SOF0, для PNG – IHDR chunk. Это полезно при обработке миллионов файлов.
Пример для JPEG:
def jpeg_size(filepath):
import struct
with open(filepath, 'rb') as f:
f.read(2)
while True:
marker = f.read(2)
if marker == b'\xff\xc0' or marker == b'\xff\xc2':
f.read(3)
height = struct.unpack('>H', f.read(2))[0]
width = struct.unpack('>H', f.read(2))[0]
return width, height
seg_len = struct.unpack('>H', f.read(2))[0] - 2
f.read(seg_len)
print(jpeg_size('image.jpg'))Python сохранить изображение (сохранение изображения с помощью python)
Метод не требует загрузки всего файла, работает быстро. Однако для разных форматов требуется своя логика.
Ошибки при таком подходе:
- Файл не является JPEG – функция вернёт None или зациклится. Необходимо проверять первые байты (0xFFD8) и ограничивать число итераций.
- Изображение может иметь несколько сегментов SOF0 (например, progressive JPEG). В этом случае каждый сегмент содержит размеры для разных компонентов. Обычно первый – полный размер.
Как раньше получали размеры с помощью scipy.misc (устаревший способ)?
В старых версиях scipy была функция scipy.misc.imread(), которая также возвращала numpy массив. Начиная с scipy 1.3.0, она удалена из основного пакета. Использовать не рекомендуется, но для совместимости с legacy-кодом можно установить пакет scipy-misc.
# ВНИМАНИЕ: scipy.misc.imread удалён
# Рекомендуется перейти на imageioДополнительные примеры и специализированные методы
Пакетное получение размеров всех изображений в папке
Данный пример обходит каталог, открывает каждый файл с помощью Pillow и записывает размеры или сообщение об ошибке. Полезно для инвентаризации медиатеки.
import os
from PIL import Image
def get_image_sizes(folder):
results = []
for file in os.listdir(folder):
path = os.path.join(folder, file)
if not os.path.isfile(path):
continue
try:
with Image.open(path) as img:
results.append((file, img.size))
except Exception as e:
results.append((file, str(e)))
return results
sizes = get_image_sizes('images/')
for name, size in sizes:
if isinstance(size, tuple):
print(f'{name}: {size[0]}x{size[1]}')
else:
print(f'{name}: Ошибка - {size}')photo1.jpg: 1920x1080 photo2.png: 800x600 broken.gif: Ошибка - cannot identify image file 'broken.gif'
Чтение размеров из EXIF-данных JPEG (без загрузки пикселей)
EXIF-теги ExifImageWidth и ExifImageLength часто содержат исходные размеры до поворота. Используя библиотеку exifread, можно получить эти значения без декодирования всего изображения.
import exifread
def get_dimensions_from_exif(filepath):
with open(filepath, 'rb') as f:
tags = exifread.process_file(f, details=False)
width = tags.get('EXIF ExifImageWidth', None)
height = tags.get('EXIF ExifImageLength', None)
if width and height:
return (int(width.values[0]), int(height.values[0]))
return None
print(get_dimensions_from_exif('photo.jpg'))(4032, 3024)
Использование ImageMagick через subprocess
Утилита identify из пакета ImageMagick позволяет получать метаданные без загрузки изображения в Python. Эффективно для больших файлов.
import subprocess
import json
def imagemagick_size(filepath):
result = subprocess.run(
['identify', '-format', '{"width":%w,"height":%h}', filepath],
capture_output=True, text=True
)
if result.returncode == 0:
return json.loads(result.stdout)
return None
print(imagemagick_size('image.jpg')){'width': 1920, 'height': 1080}Ручное чтение заголовка PNG
PNG-изображения содержат IHDR-чанк с шириной и высотой. Чтение только 24 байтов после сигнатуры позволяет определить размер, не загружая весь файл.
def png_size(filepath):
import struct
with open(filepath, 'rb') as f:
sig = f.read(8)
if sig != b'\x89PNG\r\n\x1a\n':
return None
chunk_len = struct.unpack('>I', f.read(4))[0]
chunk_type = f.read(4)
if chunk_type != b'IHDR':
return None
data = f.read(chunk_len)
width = struct.unpack('>I', data[0:4])[0]
height = struct.unpack('>I', data[4:8])[0]
return width, height
print(png_size('image.png'))(400, 300)