Кадр в памяти: форма, размер и BGR → RGB на Python

После чтения изображение занимает в памяти другой объём, чем файл на диске, а порядок каналов зависит от декодера. Реализуйте отчёт по кадру и преобразование каналов по условию; вход приходит готовыми списками, NumPy и OpenCV не нужны.

Откройте программу платного курса Computer Vision Engineer, чтобы продолжить практику с данными, моделями и CV-сервисом.

Отчёт по прочитанному кадру

Первое, что делают с кадром после cv2.imread, — смотрят, что именно прочиталось: какой формы массив, сколько он занимает в памяти и в том ли порядке лежат каналы. Соберём эту проверку в одну функцию, чтобы дальше не считать руками каждый раз.

Задание

Напишите функцию frame_report(frame, dtype, file_bytes). Она получает кадр, название типа чисел и размер исходного файла на диске в байтах, а возвращает словарь с шестью ключами:

  • height, width — высота и ширина кадра в пикселях;
  • channels — число каналов;
  • memory_kib — сколько килобайт занимает кадр в памяти, округлить до одного знака после запятой (1 КБ = 1024 байта);
  • ratio — во сколько раз память больше файла на диске, округлить до одного знака;
  • rgb — тот же кадр с каналами в порядке RGB.

Кадр приходит вложенными списками, повторяя форму массива из cv2.imread: внешний список — строки пикселей сверху вниз, внутри каждой строки — пиксели слева направо, а каждый цветной пиксель — три числа в порядке BGR.

Тип чисел приходит строкой: "uint8" — по одному байту на число, "float32" — по четыре. Это и есть разница между кадром сразу после чтения и им же после нормализации, и в объёме памяти она видна вчетверо.

Одноканальный кадр устроен иначе: у снимка в градациях серого нет третьего уровня вложенности, строка состоит просто из чисел. Тогда channels равен 1, а в rgb возвращается тот же кадр без изменений — переставлять там нечего.

Пример

# кадр 480 на 640, каждый пиксель [b, g, r], файл на диске 60 КБ
report = frame_report(frame, "uint8", 61440)

report["height"]      # 480
report["width"]       # 640
report["channels"]    # 3
report["memory_kib"]  # 900.0
report["ratio"]       # 15.0
frame_report([[[24, 108, 144]]], "uint8", 1024)["rgb"]   # [[[144, 108, 24]]]

Примечание

На платформе нет ни numpy, ни opencv, поэтому кадр и тип чисел приходят обычными объектами Python. У себя в окружении те же величины берутся из массива напрямую: форма — из frame.shape, тип — из frame.dtype, объём в памяти — из frame.nbytes.

Весь код держите внутри функции: на проверку отправляется только она, и вспомогательные переменные, объявленные рядом на верхнем уровне, до неё не доедут. Исходный кадр менять не нужно — rgb собирается отдельным списком.

Вызывать функцию самостоятельно не нужно — проверка запустит её сама на нескольких кадрах разной формы и разного типа чисел.

Что проверяется

Код проверок скрыт, так что вот полный список того, что в них разбирается:

  • формат ответа: словарь с ключами height, width, channels, memory_kib, ratio и rgb;
  • кадр 480 на 640 из примера: форма, объём в памяти и отношение к размеру файла;
  • порядок каналов на одном пикселе;
  • одноканальный кадр: channels равен 1, а rgb возвращается без изменений;
  • цветной кадр целиком: каждый пиксель развёрнут из BGR в RGB;
  • исходный кадр при этом не меняется;
  • float32 вместо uint8 — та же форма, вчетверо больше памяти;
  • прямоугольный кадр: высота и ширина не меняются местами.
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи