Как диагностировать и исправить 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} вычислена')Результат: вывод гистограмм для каждого канала без ошибок.