Получение габаритов картинок на 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)

Получение размеров изображения в Python - comments

En
Python размер изображения (python)