Как диагностировать и исправить assertion failed в OpenCV Python

Раздел: Библиотеки -> Компьютерное зрение

Основные причины возникновения ошибки assertion

Ошибка assertion failed (код -215) в OpenCV Python чаще всего сигнализирует о несоответствии ожидаемых и фактических параметров изображения или матрицы. Типовые сценарии: попытка выполнить операцию над пустым изображением, несовпадение размеров, глубины цвета или количества каналов. Далее рассмотрено наиболее универсальное решение и несколько частных случаев.

Универсальная проверка загрузки и свойств изображения

Как убедиться, что изображение корректно загружено и имеет правильные атрибуты?

Перед вызовом любой функции OpenCV, которая может выбросить assertion, следует явно проверить, что img не равно None, а также соответствие размеров и типа данных.

import cv2
import numpy as np

# Загрузка изображения
img = cv2.imread('input.jpg')

# Проверка на None
if img is None:
    print('Ошибка: изображение не загружено. Проверьте путь к файлу.')
    exit()

# Проверка типа и размеров
print(f'Тип данных: {img.dtype}')
print(f'Размер: {img.shape}')

# Пример безопасной операции
if len(img.shape) == 3 and img.shape[2] == 3:
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
    print('Изображение не 3-канальное, преобразование отменено.')

Python opencv functions (функции opencv в python)

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

  • Файл повреждён или имеет неподдерживаемый формат. Решение: использовать cv2.imdecode с явным указанием флага.
  • Путь содержит кириллицу. Решение: читать файл с помощью numpy.fromfile и затем cv2.imdecode.

Данный подход предотвращает большинство ошибок assertion, возникающих из-за неверных входных данных.

Вариант 1: Исправление несовпадения размеров при арифметических операциях

Как выполнить сложение или смешивание изображений, если их размеры различаются?

Функции cv2.add, cv2.addWeighted, cv2.bitwise_and требуют строгого совпадения размеров. Решение - привести все изображения к единому размеру через cv2.resize.

img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

if img1 is None or img2 is None:
    print('Одно из изображений не загружено')
    exit()

# Приведение img2 к размеру img1
img2_resized = cv2.resize(img2, (img1.shape[1], img1.shape[0]))

# Теперь сложение возможно
result = cv2.addWeighted(img1, 0.5, img2_resized, 0.5, 0)

Python opencv 215 assertion failed (ошибка assertion в opencv python)

Типичная ошибка:

Игнорирование порядка ширины и высоты в cv2.resize. Первый параметр - ширина (число столбцов), второй - высота (число строк). Обращение img1.shape[1] даёт ширину, img1.shape[0] - высоту.

Вариант 2: Проверка глубины цвета при конвертации

Как избежать ошибки при переводе изображения в оттенки серого, если оно уже одноканальное?

Функция cv2.cvtColor ожидает 3-канальное изображение для кода COLOR_BGR2GRAY. Если изображение чёрно-белое или имеет альфа-канал, возникает assertion.

img = cv2.imread('grayscale.png', cv2.IMREAD_UNCHANGED)
print(img.shape)  # может быть (H, W) или (H, W, 4)

if len(img.shape) == 2 or (len(img.shape) == 3 and img.shape[2] == 1):
    # Изображение уже одноканальное
    gray = img
elif len(img.shape) == 3 and img.shape[2] == 4:
    # Удаление альфа-канала
    bgr = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
    gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
else:
    # Стандартный случай
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

библиотека cv2 python (библиотека opencv в python)

Распространённая проблема:

Флаг cv2.IMREAD_UNCHANGED загружает изображение с альфа-каналом, что может нарушить ожидания функций, не поддерживающих 4 канала.

Вариант 3: Проверка типа данных при арифметических операциях

Как выполнить вычисления с изображениями разных типов (uint8, float32)?

OpenCV ожидает, что оба изображения имеют одинаковый тип данных. Решение - привести к одному типу через .astype().

img1 = cv2.imread('a.jpg').astype(np.float32) / 255.0
img2 = cv2.imread('b.jpg').astype(np.float32) / 255.0

# После приведения к float32 сложение не вызывает ошибок
result = cv2.add(img1, img2)

# Обратно в uint8 для сохранения
result_uint8 = (result * 255).astype(np.uint8)

Python изображения (работа с изображениями в python)

Предупреждение:

При работе с float32 значения должны лежать в диапазоне [0,1] или [0,255] в зависимости от контекста. Ошибка может возникнуть и при выходе за допустимый диапазон.

Вариант 4: Ошибка при копировании изображения (deep copy vs shallow copy)

Почему после img2 = img1 изменение одного изображения влияет на другое?

Присваивание в Python не создаёт копию массива. Использование img.copy() обязательно, если требуется независимая копия, иначе операции над копией могут изменить оригинал, что иногда приводит к неожиданным assertion при повторном использовании.

img = cv2.imread('photo.jpg')
img_copy = img.copy()        # независимая копия
img_view = img               # ссылка на тот же объект

# Изменение копии не затрагивает оригинал
img_copy[0,0] = [0,0,0]
print(img[0,0])              # исходное значение

Расширенные примеры работы с ошибкой assertion

Пример 1: Обработка видеофайла с контролем кадров

При чтении видео кадры могут заканчиваться, и попытка обработать None вызовет assertion. Ниже приведён безопасный цикл с проверкой.

Пример
import cv2

cap = cv2.VideoCapture('video.mp4')
if not cap.isOpened():
    print('Не удалось открыть видео')
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        print('Конец видео или ошибка чтения')
        break
    # Проверка, что frame не None
    assert frame is not None, 'Получен пустой кадр'
    # Обработка кадра (например, изменение размера)
    small = cv2.resize(frame, (640, 480))
    cv2.imshow('Frame', small)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
Результат: видео проигрывается до конца или до нажатия 'q'. В случае пустого кадра цикл прервётся без ошибки.

Типичная ошибка:

Использование cv2.resize на None. Приводит к 'Assertion failed (src.data != NULL)'. Решение – всегда проверять успешность read().

Пример 2: Маскирование с использованием bitwise_and при несовпадающих размерах

Часто требуется применить маску к изображению. Ошибка возникает, если маска меньше или больше исходного изображения.

Пример
img = cv2.imread('scene.jpg')
mask = cv2.imread('mask.png', cv2.IMREAD_GRAYSCALE)

# Приведение маски к размеру изображения
if mask.shape != img.shape[:2]:
    mask = cv2.resize(mask, (img.shape[1], img.shape[0]), interpolation=cv2.INTER_NEAREST)

# Применение маски (mask должна быть двумерной, а img трёхмерной)
masked = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('Masked', masked)
Результат: корректное наложение маски. Если маска имеет 3 канала, возникает ошибка - требуется одноканальная маска.

Пример 3: Имитация ошибки и её отладка через assert собственный

Полезно самостоятельно выбрасывать исключение с понятным сообщением.

Пример
def safe_resize(img, width, height):
    assert img is not None, 'Изображение не загружено'
    assert img.shape[0] > 0 and img.shape[1] > 0, 'Размеры изображения некорректны'
    return cv2.resize(img, (width, height))

img = cv2.imread('nonexistent.jpg')
try:
    resized = safe_resize(img, 400, 300)
except AssertionError as e:
    print(f'Ошибка: {e}')
Вывод: Ошибка: Изображение не загружено

Пример 4: Использование cv2.imdecode для чтения из байтов (кириллица в пути)

Когда путь содержит нелатинские символы, cv2.imread возвращает None. Решение – чтение через numpy.fromfile.

Пример
import numpy as np

path = 'C:/Users/Пользователь/image.jpg'
with open(path, 'rb') as f:
    file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
img = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
if img is None:
    print('Ошибка декодирования')
else:
    cv2.imshow('Image', img)
Результат: изображение отображается независимо от кодировки пути.

Пример 5: Проверка количества каналов перед cv2.calcHist

Функция cv2.calcHist ожидает список изображений, каждое из которых должно быть одноканальным. Если передать цветное изображение, возникнет assertion.

Пример
img = cv2.imread('color.jpg')
# Разделение на каналы
channels = cv2.split(img)
hist = []
for i, ch in enumerate(channels):
    hist.append(cv2.calcHist([ch], [0], None, [256], [0,256]))
    print(f'Гистограмма канала {i} вычислена')
Результат: вывод гистограмм для каждого канала без ошибок.

Ошибка assertion в OpenCV Python - comments

En
Python opencv 215 assertion failed (python)