В этой инструкции создадим рабочую умную камеру на Python: OpenCV получит изображение с веб-камеры, обнаружит движение, прочитает QR-код и сохранит кадр события. В конце разберём подключение RTSP-камеры и обученной модели YOLO.
Актуально на 22 июня 2026 года. Команды проверены по карточке opencv-python и официальным руководствам OpenCV по работе с видео, вычитанию фона и QRCodeDetector. На дату статьи стабильный пакет в PyPI — 4.13.0.92.
Что получится
- окно с живым изображением и FPS;
- рамки вокруг крупных движущихся областей;
- чтение QR-кода без отдельного облачного сервиса;
- снимок в папке
eventsне чаще одного раза в пять секунд; - понятная основа для IP-камеры или YOLO.

Что понадобится
- Python и веб-камера либо тестовый видеофайл;
- Windows, macOS или Linux;
- около 500 МБ свободного места с запасом;
- разрешение операционной системы на доступ к камере.
OpenCV может обрабатывать изображение локально. Это не отменяет требований к приватности: не снимайте людей без законного основания и не публикуйте RTSP-адрес, логин или пароль.
Шаг 1. Создайте проект и виртуальное окружение
macOS и Linux:
mkdir opencv-smart-camera
cd opencv-smart-camera
python3 -m venv .venv
source .venv/bin/activate
Windows PowerShell:
mkdir opencv-smart-camera
cd opencv-smart-camera
py -m venv .venv
.venv\Scripts\Activate.ps1
Шаг 2. Установите OpenCV
python -m pip install --upgrade pip
python -m pip install opencv-python
python -c "import cv2; print(cv2.__version__)"
Устанавливайте только один вариант OpenCV в одном окружении. Для сервера без окон и без cv2.imshow() используйте opencv-python-headless. Дополнительные модули находятся в opencv-contrib-python; одновременно с обычным пакетом его ставить не следует.

opencv-python, но импортируется как cv2.Шаг 3. Проверьте доступ к камере
import cv2
camera = cv2.VideoCapture(0)
if not camera.isOpened():
raise SystemExit("Cannot open camera")
while True:
ok, frame = camera.read()
if not ok:
break
cv2.imshow("Camera test", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
camera.release()
cv2.destroyAllWindows()
Сохраните код как camera_test.py и выполните python camera_test.py. Если камера не открылась, закройте Zoom и другие программы, проверьте системное разрешение и попробуйте индекс 1.
Шаг 4. Как определяется движение
createBackgroundSubtractorMOG2() строит модель неподвижного фона. Текущий кадр сравнивается с этой моделью, затем бинарная маска очищается морфологическими операциями. Контуры меньше MIN_AREA отбрасываются как шум. Первые секунды после запуска модель адаптируется, поэтому ложные рамки в начале ожидаемы.
Шаг 5. Создайте полный скрипт умной камеры
Создайте smart_camera.py:
from datetime import datetime
from pathlib import Path
import time
import cv2
import numpy as np
CAMERA_SOURCE = 0
MIN_AREA = 2500
SAVE_COOLDOWN = 5.0
OUTPUT_DIR = Path("events")
OUTPUT_DIR.mkdir(exist_ok=True)
camera = cv2.VideoCapture(CAMERA_SOURCE)
if not camera.isOpened():
raise SystemExit("Cannot open camera")
motion_model = cv2.createBackgroundSubtractorMOG2(
history=500, varThreshold=36, detectShadows=True
)
qr_detector = cv2.QRCodeDetector()
kernel = np.ones((3, 3), dtype=np.uint8)
last_saved_at = 0.0
previous_tick = time.perf_counter()
try:
while True:
ok, frame = camera.read()
if not ok:
break
height, width = frame.shape[:2]
target_width = min(960, width)
scale = target_width / width
frame = cv2.resize(frame, (target_width, int(height * scale)))
mask = motion_model.apply(frame)
_, mask = cv2.threshold(mask, 200, 255, cv2.THRESH_BINARY)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2)
mask = cv2.dilate(mask, kernel, iterations=2)
motion = False
contours, _ = cv2.findContours(
mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
for contour in contours:
if cv2.contourArea(contour) < MIN_AREA:
continue
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 220, 180), 2)
motion = True
qr_text, qr_points, _ = qr_detector.detectAndDecode(frame)
if qr_text and qr_points is not None:
points = qr_points.astype(int).reshape(-1, 2)
cv2.polylines(frame, [points], True, (0, 210, 255), 3)
cv2.putText(frame, f"QR: {qr_text[:40]}", (20, 70),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 210, 255), 2)
now = time.monotonic()
if motion and now - last_saved_at >= SAVE_COOLDOWN:
name = datetime.now().strftime("event_%Y%m%d_%H%M%S.jpg")
cv2.imwrite(str(OUTPUT_DIR / name), frame)
last_saved_at = now
tick = time.perf_counter()
fps = 1.0 / max(tick - previous_tick, 1e-6)
previous_tick = tick
status = "MOTION" if motion else "READY"
cv2.putText(frame, f"{status} | FPS {fps:.1f}", (20, 35),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 220, 180), 2)
cv2.imshow("OpenCV smart camera", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
finally:
camera.release()
cv2.destroyAllWindows()
Шаг 6. Запустите и настройте чувствительность
python smart_camera.py
MIN_AREAувеличьте, если камера реагирует на мелкие тени;varThresholdувеличьте при шумной картинке;SAVE_COOLDOWNзадаёт минимальную паузу между снимками;- нажмите
Q, чтобы корректно освободить камеру.

Шаг 7. Подключите видео или RTSP-камеру
Вместо индекса веб-камеры можно указать файл:
CAMERA_SOURCE = "video.mp4"
Или RTSP-адрес, выданный производителем камеры:
CAMERA_SOURCE = "rtsp://USER:PASSWORD@CAMERA_IP:554/STREAM_PATH"
Не вставляйте реальный пароль в Git и скриншоты. Храните секрет отдельно, ограничьте доступ к камере локальной сетью и не пробрасывайте RTSP-порт напрямую в интернет.
Шаг 8. Подключите YOLO26
Если нужно различать человека, автомобиль или собственные классы, установите Ultralytics и загрузите обученный best.pt:
python -m pip install ultralytics
from ultralytics import YOLO
model = YOLO("best.pt")
results = model.predict(frame, conf=0.35, verbose=False)
annotated_frame = results[0].plot()
Такой блок помещают после чтения кадра. Для начала запускайте нейросеть на каждом втором или третьем кадре: это уменьшит нагрузку. Полное обучение модели разобрано в отдельной инструкции по YOLO26.
Частые ошибки
- Камера не открывается: проверьте разрешения ОС, индекс и занявшие камеру приложения.
- Нет окна на сервере: headless-пакет не поддерживает
imshow; сохраняйте кадры или передавайте их через веб-интерфейс. - Слишком много событий: увеличьте
MIN_AREAиSAVE_COOLDOWN. - Видео не записывается: контейнер, FourCC и доступный кодек должны быть совместимы.
- QR не читается: улучшите освещение, приблизьте код и избегайте бликов.
FAQ
Нужна ли видеокарта?
Для движения и QR-кодов — нет. GPU становится важнее при подключении тяжёлой нейросети.
Почему пакет называется opencv-python, а импорт cv2?
opencv-python — имя пакета в PyPI, а cv2 — историческое имя Python-модуля.
Можно ли запускать на Raspberry Pi?
Да, но совместимость готового wheel и скорость зависят от архитектуры, ОС и камеры. Уменьшайте разрешение и частоту обработки.
Вывод
OpenCV позволяет собрать полезный прототип без облачного сервиса: получить видеопоток, выделить движение, прочитать QR-код и сохранить событие. Сначала добейтесь стабильной работы с веб-камерой, затем подключайте RTSP и YOLO по одному — так проще найти источник ошибки.
Обложка создана генеративной моделью. Пошаговые изображения являются обезличенными демонстрационными схемами и не содержат реальных адресов камер, учётных данных или персональной информации.

Комментарии к статье