cv2 называется модуль, через который Python подключает библиотеку OpenCV. Отдельного пакета cv2 нет: ставится он командой pip install opencv-python, а в коде пишется import cv2. После установки проверьте версию одной строкой print(cv2.__version__). Если она напечаталась, можно читать картинки, менять их размер, искать на фото лица и разбирать видео по кадрам.
Ниже разобраны установка, первые программы и ошибки, из-за которых у новичков не запускается код. Весь код мы запустили в Python 3.14 на двух версиях OpenCV, 5.0 и 4.14, и показали реальный вывод. Если вам интересно, кем можно работать с этой библиотекой, загляните в разбор профессии CV-инженера.
SkillboxПрофессия «Data Scientist PRO»224 595 ₽12 месяцев
НетологияПрофессия «Data Scientist: с нуля до middle»189 000 ₽17 месяцев
OTUSPython Developer180 000 ₽10 месяцев
TeachMeSkillsMachine learning130 000 ₽8 месяцев
ЭдюсонMachine Learning145 900 ₽7 месяцев
НетологияПрофессия «Data Scientist»83 400 ₽10 месяцев
Как установить cv2 через pip

Ставить библиотеку лучше в виртуальное окружение, а не в системный Python: тогда разные проекты не мешают друг другу версиями.
- Создайте окружение командой
python -m venv venvи активируйте его. - Установите пакет:
python -m pip install opencv-python. Вместе с ним приедет NumPy, без него OpenCV не работает. - Проверьте, что всё встало.
import cv2
print(cv2.__version__)
5.0.0
Команда pip install cv2 не сработает, такого пакета в каталоге PyPI нет:
ERROR: Could not find a version that satisfies the requirement cv2 (from versions: none)
ERROR: No matching distribution found for cv2
Какой из четырёх пакетов выбрать
На странице opencv-python в PyPI перечислены четыре варианта сборки. Импортируются все четыре одинаково, как cv2.
| Пакет | Что внутри | Когда брать |
|---|---|---|
| opencv-python | основные модули и окна для показа картинок | учёба и обычные скрипты на своём компьютере |
| opencv-contrib-python | основные модули плюс дополнительные из opencv_contrib | нужны алгоритмы, которых нет в основной сборке |
| opencv-python-headless | основные модули без графического интерфейса | сервер, Docker, облако, где окна не нужны |
| opencv-contrib-python-headless | основные и дополнительные модули без интерфейса | серверу нужны модули contrib |
Разработчики пакета просят ставить в одно окружение только один из четырёх. Модуль у всех называется cv2, и пакеты перезаписывают друг друга. Если вы уже поставили два, удалите все через pip uninstall и установите один заново.
Чтобы узнать, какой из пакетов уже стоит в окружении, посмотрите список через pip. Вот вывод из нашего тестового окружения, где стояла серверная сборка:
python -m pip list | grep -i -E "opencv|numpy"
numpy 2.5.4
opencv-python-headless 5.0.0.93
На Windows вместо grep подойдёт findstr /i opencv или просто полный pip list. Если в выводе две строки с opencv, это та самая ситуация, когда пакеты перезаписывают друг друга, и одну из них нужно убрать.
Какую версию ставить: пятую или четвёртую
Летом 2026 года OpenCV выпустил две ветки: 5.0.0.93 появилась в PyPI 2 июля, а 4.14.0.94 вышла 28 июля. Обычный pip install поставит пятую версию. Если код из урока или чужого проекта написан под 4.x, закрепите старую ветку:
python -m pip install "opencv-python<5"
С этим ограничением pip выбирает opencv-python 4.14.0.94. Чем ветки различаются на практике, видно ниже по разделам про текст и про поиск лиц.
Первая программа: открыть, показать и сохранить картинку
Положите рядом со скриптом любое фото, например photo.jpg. Функция cv2.imread() читает файл и возвращает массив NumPy:
import cv2
img = cv2.imread("photo.jpg")
print(type(img))
print(img.shape, img.dtype)
<class 'numpy.ndarray'>
(342, 548, 3) uint8
В shape числа идут в порядке «высота, ширина, число каналов». У нашего снимка 342 строки пикселей, 548 столбцов и три цветовых канала, каждое значение от 0 до 255.
Показать картинку в окне можно через imshow:
import cv2
img = cv2.imread("photo.jpg")
cv2.imshow("Фото", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Строка cv2.waitKey(0) нужна. В документации модуля highgui сказано, что без вызова waitKey или pollKey окно не покажет изображение и может зависнуть. Ноль в скобках значит «ждать нажатия клавиши сколько угодно».
Сохраняется результат функцией cv2.imwrite("result.jpg", img). Формат она берёт из расширения: .jpg, .png, .webp и другие.
Если imread вернул None
Главная ловушка для новичков: imread не падает с ошибкой, если файла нет. Он печатает предупреждение и возвращает пустое значение, а программа ломается строкой ниже, на первой операции с картинкой.
import cv2
img = cv2.imread("phto.jpg")
print(img)
[ WARN:0@0.003] global loadsave.cpp:278 findDecoder imread_('phto.jpg'): can't open/read file: check file path/integrity
None
Так ведёт себя функция и по описанию в исходниках OpenCV: если файл нельзя прочитать из-за опечатки в пути, прав доступа или неподдерживаемого формата, возвращается пустая матрица. В Python это None.
Решение: после чтения проверяйте результат строкой if img is None: и выводите путь, который не открылся. Путь относительный? Он считается от папки, откуда запущен скрипт, а не от папки с файлом .py. Подробнее об этом в инструкции о том, как запускать скрипт Python из командной строки.
Почему цвета «поехали»: BGR вместо RGB

OpenCV хранит цветные картинки в порядке каналов синий, зелёный, красный, а не привычном RGB. Это записано в той же документации imread. Пока вы работаете только внутри OpenCV, разницы не видно. Но стоит передать массив в Matplotlib или Pillow, и лица на фото станут синими.
import cv2
img = cv2.imread("photo.jpg")
print(img[0, 0])
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(rgb[0, 0])
[39 43 44]
[44 43 39]
Левый верхний пиксель тот же, только первый и третий канал поменялись местами. Перед тем как отдать картинку другой библиотеке, переводите её через cv2.COLOR_BGR2RGB.
Основные операции с изображением
Картинка в OpenCV хранится как массив NumPy, поэтому с массивами придётся работать постоянно. Если с ними пока неуверенно, посмотрите курсы по NumPy.
Большая часть повседневной работы с картинками укладывается в несколько функций:
| Задача | Функция |
|---|---|
| изменить размер | cv2.resize() |
| перевести в серый или HSV | cv2.cvtColor() |
| вырезать фрагмент | срез массива img[y1:y2, x1:x2] |
| повернуть на 90 или 180 градусов | cv2.rotate() |
| повернуть на любой угол | cv2.getRotationMatrix2D() и cv2.warpAffine() |
| размыть | cv2.GaussianBlur(), cv2.medianBlur() |
| сделать чёрно-белую маску | cv2.threshold() |
| найти границы предметов | cv2.Canny() |
Размер, цвет и обрезка
import cv2
img = cv2.imread("photo.jpg")
small = cv2.resize(img, (274, 171))
half = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
crop = img[50:250, 200:400]
print(small.shape, half.shape)
print(gray.shape)
print(crop.shape)
cv2.imwrite("gray.jpg", gray)
(171, 274, 3) (171, 274, 3)
(342, 548)
(200, 200, 3)
Обратите внимание на порядок координат. В resize размер передаётся как (ширина, высота), а в срезе массива сначала идут строки, то есть высота. Перепутать их легко, и картинка получится растянутой.
Срез картинки устроен так же, как срез списка в Python, только по двум осям сразу: сначала строки, через запятую столбцы.
Для уменьшения документация imgproc советует INTER_AREA, а для увеличения INTER_CUBIC (медленнее) или INTER_LINEAR (быстрее). Серую картинку можно получить и сразу при чтении: cv2.imread("photo.jpg", cv2.IMREAD_GRAYSCALE).
Поворот
import cv2
img = cv2.imread("photo.jpg")
r90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
print(r90.shape)
h, w = img.shape[:2]
M = cv2.getRotationMatrix2D((w / 2, h / 2), 30, 1.0)
r30 = cv2.warpAffine(img, M, (w, h))
print(r30.shape)
(548, 342, 3)
(342, 548, 3)
При повороте на 90 градусов ширина и высота меняются местами. Поворот на 30 градусов сохраняет размер холста, поэтому углы картинки обрезаются, а освободившиеся места заливаются чёрным.
Размытие, порог и границы
import cv2
img = cv2.imread("photo.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
_, bw = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY)
edges = cv2.Canny(blur, 100, 200)
print(bw.min(), bw.max())
print(cv2.countNonZero(edges))
cv2.imwrite("edges.jpg", edges)
0 255
4546
После порога в картинке остаются только два значения, 0 и 255. Детектор Canny нашёл 4 546 пикселей-границ. Размытие перед ним убирает шум, иначе в границы попадёт зерно снимка.
Как рисовать на картинке и подписывать её
Прямоугольник вокруг найденного объекта, точка, линия и подпись делаются четырьмя функциями. Цвет задаётся тоже в порядке BGR: (0, 255, 0) даёт зелёный, (0, 0, 255) красный.
import cv2
img = cv2.imread("photo.jpg")
cv2.rectangle(img, (20, 20), (220, 120), (0, 255, 0), 2)
cv2.circle(img, (400, 80), 40, (0, 0, 255), -1)
cv2.line(img, (0, 330), (547, 330), (255, 0, 0), 3)
cv2.putText(img, "OpenCV", (30, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 255), 2)
cv2.putText(img, "Привет", (30, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 255), 2)
cv2.imwrite("drawn.jpg", img)
Последний аргумент у фигур задаёт толщину линии. Значение -1 заливает фигуру целиком.
С кириллицей версии ведут себя по-разному. На OpenCV 4.14 вместо слова «Привет» на картинке появились двенадцать вопросительных знаков: шрифты Hershey не рисуют кириллицу, а такие символы функция putText, как сказано в её описании, заменяет вопросительными знаками. На 5.0 тот же код вывел «Привет» нормально. В руководстве по переходу с 4 на 5 сказано, что новый вывод текста поддерживает строки UTF-8 и свои шрифты .ttf и .otf.
Решение для 4.x: подписывайте латиницей или рисуйте текст через Pillow и возвращайте картинку в OpenCV.
Видео и веб-камера
Видео для OpenCV состоит из отдельных картинок-кадров. Класс cv2.VideoCapture открывает файл и отдаёт кадры по одному через read(). Ниже мы сначала собрали короткий ролик из фото, а потом прочитали его обратно:
import cv2
img = cv2.imread("photo.jpg")
h, w = img.shape[:2]
out = cv2.VideoWriter("clip.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 25, (w, h))
for i in range(50):
out.write(img)
out.release()
cap = cv2.VideoCapture("clip.mp4")
print(cap.get(cv2.CAP_PROP_FRAME_COUNT), cap.get(cv2.CAP_PROP_FPS))
frames = 0
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frames += 1
cap.release()
print("Кадров прочитано:", frames)
50.0 25.0
Кадров прочитано: 50
Метод read() возвращает пару: флаг ret и сам кадр. Когда видео кончилось, флаг становится False, и цикл пора останавливать: для этого в примере стоит оператор break. Без этой проверки программа упадёт на пустом кадре.
Чтобы взять картинку с веб-камеры, вместо имени файла передайте число: cv2.VideoCapture(0). По документации модуля videoio ноль открывает камеру по умолчанию. Цикл чтения тот же. Камеру надо освобождать через cap.release(), иначе другие программы её не получат. Чтобы это случилось и при ошибке внутри цикла, поставьте release в блок finally, как в разборе try и except в Python.
Как найти лица на фото: каскад Хаара и детектор YuNet

В большинстве уроков лица ищут каскадом Хаара. На OpenCV 4.14 он работает из коробки, файлы каскадов лежат внутри пакета:
import cv2
path = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(path)
img = cv2.imread("photo.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
print("Лиц найдено:", len(faces))
for (x, y, w, h) in faces:
print(x, y, w, h)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imwrite("faces.jpg", img)
Лиц найдено: 1
227 94 37 37
Параметр minNeighbors отсекает ложные срабатывания: чем он больше, тем строже отбор. Если рамки появляются там, где лиц нет, увеличьте его.
На OpenCV 5.0 тот же код падает на второй строке:
AttributeError: module 'cv2' has no attribute 'CascadeClassifier'
Причина описана в руководстве по переходу: каскады Хаара и HOGDescriptor перенесли в модуль xobjdetect из opencv_contrib. Мы поставили opencv-contrib-python-headless 5.0: класс появился, но XML-файлов каскадов в папке cv2/data уже нет, и вызов detectMultiScale заканчивается ошибкой Assertion failed: !empty().
Для новых проектов разработчики предлагают присмотреться к нейросетевому детектору из основного модуля. Это cv2.FaceDetectorYN с моделью YuNet. Файл модели face_detection_yunet_2023mar.onnx весит 227 КБ, скачивается из репозитория opencv_zoo и кладётся рядом со скриптом.
import cv2
img = cv2.imread("photo.jpg")
h, w = img.shape[:2]
detector = cv2.FaceDetectorYN.create("face_detection_yunet_2023mar.onnx", "", (w, h))
_, faces = detector.detect(img)
print("Лиц найдено:", 0 if faces is None else len(faces))
for f in faces if faces is not None else []:
x, y, fw, fh = map(int, f[:4])
print(x, y, fw, fh, round(float(f[-1]), 2))
cv2.rectangle(img, (x, y), (x + fw, y + fh), (0, 255, 0), 2)
cv2.imwrite("faces.jpg", img)
Лиц найдено: 1
225 93 30 39 0.92
Последнее число показывает уверенность модели: 0,92 из 1. Этот код одинаково отработал на 4.14 и на 5.0. На пятой версии перед результатом он ещё печатает служебное предупреждение setPreferableTarget Targets are not supported by the new graph engine, на результат оно не влияет.
Частые ошибки и что с ними делать
| Что видите | Причина | Что сделать |
|---|---|---|
ModuleNotFoundError: No module named 'cv2' |
пакет установлен в другой Python или в другое окружение | ставить через python -m pip install opencv-python тем же интерпретатором, которым запускаете скрипт |
No matching distribution found for cv2 |
пакета с именем cv2 не существует | pip install opencv-python |
imread вернул None |
опечатка в пути или скрипт запущен из другой папки | проверять img is None, писать полный путь |
окно imshow не рисуется или висит |
нет cv2.waitKey() |
добавить cv2.waitKey(0) после imshow |
на Windows: ImportError: DLL load failed |
нет системных библиотек Visual C++ | установить Visual C++ redistributable, а в редакциях Windows N и KN ещё и Media Feature Pack |
| после установки двух пакетов OpenCV «ломается» | пакеты пишут в один и тот же модуль cv2 | удалить все пакеты opencv и поставить один |
AttributeError: ... 'CascadeClassifier' |
OpenCV 5.0, каскады переехали в contrib | FaceDetectorYN или "opencv-python<5" |
С первой ошибкой из таблицы история обычно такая: pip ставит пакет в один Python, а редактор запускает код другим. Разбор с примерами для похожей библиотеки есть в инструкции, как установить PyGame и исправить ModuleNotFoundError: схема для cv2 та же.
Про DLL на Windows подробно написано в разделе вопросов на странице пакета в PyPI. Там же совет на случай, если не помогло: открыть файл cv2.pyd программой Dependencies и посмотреть, какой библиотеки не хватает.
Кириллица в пути к файлу
Русские буквы в пути ломают чтение по-своему, например C:\Фото\кот.jpg. На части систем Windows imread такой файл не открывает и молча возвращает None. Команда OpenCV решила не добавлять отдельный API для таких путей: поведение зависит от поддержки UTF-8 в системе и от локали. В качестве обхода разработчики предлагают читать файл в память самостоятельно и декодировать через imdecode:
import cv2
import numpy as np
data = np.fromfile("фото.jpg", dtype=np.uint8)
img = cv2.imdecode(data, cv2.IMREAD_COLOR)
print(img.shape)
ok, buf = cv2.imencode(".png", img)
buf.tofile("результат.png")
print(ok)
(342, 548, 3)
True
Здесь файл открывает сам Python, а OpenCV получает уже байты, поэтому путь до него не доходит. Удобно завести в проекте свою функцию чтения на этой паре строк.
Где освоить Python и компьютерное зрение системно
Прочитать картинку и найти на ней лицо можно за первые полчаса с OpenCV. Дальше начинаются вещи, которые по кусочкам из инструкций собирать долго: NumPy и линейная алгебра, обучение своих моделей, трекинг объектов на видео, подготовка датасетов и вывод моделей в рабочий сервис.
Если хотите идти в эту сторону, сравните курсы по компьютерному зрению и отдельные программы с OpenCV. Если сначала нужен уверенный Python, начните с курсов по Python, вот пять из каталога:
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Профессия «Python-разработчик» Перейти на сайт курса | 157 335 ₽ | 5987 ₽/мес. | 10 месяцев | Обзор курса | |
| Fullstack-разработчик на Python Перейти на сайт курса | 137 000 ₽ | 7125 ₽/мес. | 21 месяц | Обзор курса | |
| ДО Профессия Python-разработчик Перейти на сайт курса | 149 001 ₽ | 3167 ₽/мес. | 10 месяцев | Обзор курса | |
| Автоматизированное тестирование на Python Перейти на сайт курса | 118 754 ₽ | 4108 ₽/мес. | 9 месяцев | Обзор курса | |
| Профессия Python-разработчик Перейти на сайт курса | 140 040 ₽ | 3890 ₽/мес. | 10 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по Python




