OPENCV НА PYTHON | Часть 1 | БАЗОВЫЕ ЗНАНИЯ
УЧЕБНОЕ ПОСОБИЕ ПО OPEN CV НА PYTHON 3.13 (часть 1)
Содержание
- Урок 1
Введение в компьютерное зрение и базовые понятия
- Урок 2
Чтение и отображение изображений, видео и работа с веб-камерой
- Урок 3
Базовые функции обработки изображений
- Урок 4
Морфологические операции
- Урок 5
Изменение размера и обрезка изображений
- Урок 6
Рисование фигур и текста на изображениях
- Урок 7
Перспективные преобразования и объединение изображений
Урок 1: Введение в компьютерное зрение и базовые понятия
1.1 Что такое изображение в цифровом виде?
Теоретическая основа:
- Изображение представляет собой матрицу (массив) пикселей
- Каждый пиксель содержит информацию о цвете или яркости
- Разрешение изображения определяется количеством пикселей по ширине и высоте:
- VGA: 640×480 пикселей
- HD: 1280×720 пикселей
- Full HD: 1920×1080 пикселей
Типы изображений:
- Бинарное изображение - содержит только два значения:
- 0 = черный цвет
- 1 = белый цвет
- Применяется для простых масок и базовой сегментации
- Изображение в градациях серого - использует 8-битное представление:
- Диапазон значений: 0-255
- 0 = абсолютный черный
- 255 = абсолютный белый
- 254 промежуточных оттенка серого
- Формат: (высота × ширина)
- Цветное изображение (RGB/BGR) - состоит из трех каналов:
- В OpenCV используется порядок BGR (Blue, Green, Red), а не RGB
- Каждый канал содержит значения от 0 до 255
- Формат: (высота × ширина × 3 канала)
1.2 Среда разработки
Необходимые инструменты:
- Python 3.13
- PyCharm Community Edition (бесплатная IDE)
- Библиотеки: OpenCV, NumPy
Пошаговая инструкция:
- Скачиваем Python с официального сайта python.org
- Важно отметить галочку "Add Python to PATH" во время установки
- Устанавливаем PyCharm Community Edition:
- Скачиваем с jetbrains.com/pycharm
- Ассоциируем .py файлы с PyCharm
- Добавляем лаунчер в PATH
- Создаем виртуальное окружение:
# В PyCharm: File → New Project → Python # Выбираем интерпретатор Python 3.13 - Устанавливаем необходимые библиотеки:
pip install opencv-python numpy
Проверка установки:
import cv2
import numpy as np
print("OpenCV версия:", cv2.__version__)
print("NumPy версия:", np.__version__)
print("Пакеты успешно импортированы!")
- OpenCV (cv2) - основная библиотека для компьютерного зрения
- NumPy (np) - библиотека для работы с многомерными массивами, необходима для математических операций с изображениями
- Версия Python влияет на совместимость некоторых функций OpenCV
Урок 2: Чтение и отображение изображений, видео и работа с веб-камерой
2.1 Чтение и отображение изображений
Используемые методы:
cv2.imread(path)- загружает изображение из файла- Параметр
path- путь к файлу изображения - Возвращает объект изображения в формате BGR
- Если файл не найден, возвращает None (не вызывает исключение!)
- Параметр
cv2.imshow(window_name, image)- отображает изображение в окнеwindow_name- название окна для отображенияimage- объект изображения для отображения- Создает окно с заданным именем и показывает в нем изображение
cv2.waitKey(delay)- ожидает нажатия клавишиdelay- время ожидания в миллисекундах (0 = бесконечно)- Возвращает код нажатой клавиши
- Обязательно вызывать после
imshowдля отображения изображения
Практический пример:
import cv2
# Чтение изображения из файла
img = cv2.imread('resources/lena.png')
# Проверка успешности загрузки
if img is None:
print("Ошибка: изображение не найдено!")
else:
# Отображение изображения
cv2.imshow('Output', img)
# Ожидание нажатия клавиши (0 - бесконечное ожидание)
cv2.waitKey(0)
# Закрытие всех окон OpenCV
cv2.destroyAllWindows()
- OpenCV использует цветовое пространство BGR вместо RGB
- Путь к файлу может быть относительным или абсолютным
- Функция
destroyAllWindows()освобождает все ресурсы, связанные с окнами OpenCV
2.2 Работа с видео
Используемые методы:
cv2.VideoCapture(source)- создает объект для захвата видеоsource- путь к видеофайлу или ID камеры- Возвращает объект VideoCapture
cap.read()- считывает следующий кадр из видео- Возвращает кортеж (success, image)
success- булево значение, указывающее на успешность чтенияimage- объект изображения (кадр)
cap.isOpened()- проверяет, успешно ли открыт источник видеоcap.release()- освобождает ресурсы видеоисточника
Практический пример:
import cv2
# Захват видео из файла
cap = cv2.VideoCapture('resources/test_video.mp4')
# Проверка успешности открытия
if not cap.isOpened():
print("Ошибка: не удалось открыть видеофайл")
exit()
while True:
# Чтение кадра
success, img = cap.read()
# Проверка успешности чтения кадра
if not success:
print("Видео закончилось или произошла ошибка")
break
# Отображение кадра
cv2.imshow('Video', img)
# Выход при нажатии клавиши 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Очистка ресурсов
cap.release()
cv2.destroyAllWindows()
cv2.waitKey(1)с параметром 1 мс обеспечивает плавное воспроизведение0xFF == ord('q')гарантирует корректную работу на 64-битных системах- Видео обрабатывается в цикле while, что позволяет обрабатывать каждый кадр
2.3 Работа с веб-камерой
Используемые методы:
cv2.VideoCapture(0)- подключение к веб-камере (ID 0 - камера по умолчанию)cap.set(propId, value)- установка параметров камеры:propId = 3- ширина кадраpropId = 4- высота кадраpropId = 10- яркостьpropId = 15- контрастность
Практический пример:
import cv2
# Захват видео с веб-камеры (ID 0 - камера по умолчанию)
cap = cv2.VideoCapture(0)
# Проверка подключения камеры
if not cap.isOpened():
print("Ошибка: не удалось подключиться к веб-камере")
exit()
# Установка параметров камеры
cap.set(3, 640) # Ширина (ID параметра 3)
cap.set(4, 480) # Высота (ID параметра 4)
cap.set(10, 100) # Яркость (ID параметра 10)
print(f"Разрешение камеры: {cap.get(3)}x{cap.get(4)}")
print(f"Яркость: {cap.get(10)}")
while True:
success, img = cap.read()
if not success:
print("Ошибка: не удалось получить кадр с камеры")
break
cv2.imshow('Webcam', img)
# Выход при нажатии клавиши 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Очистка ресурсов
cap.release()
cv2.destroyAllWindows()
- ID камеры начинается с 0 (основная камера), 1 (вторая камера) и т.д.
- Параметры камеры могут варьироваться в зависимости от модели и драйверов
- Важно всегда вызывать
cap.release()для корректного закрытия камеры - Разрешение камеры влияет на производительность и качество обработки
Урок 3: Базовые функции обработки изображений
3.1 Конвертация цветовых пространств
Используемые методы:
cv2.cvtColor(src, code)- конвертация цветового пространстваsrc- исходное изображениеcode- код преобразования:cv2.COLOR_BGR2GRAY- BGR в градации серогоcv2.COLOR_BGR2HSV- BGR в HSV (Hue, Saturation, Value)cv2.COLOR_GRAY2BGR- градации серого в BGR
Практический пример:
import cv2
# Чтение изображения
img = cv2.imread('resources/lena.png')
# Конвертация в градации серого
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Отображение результатов
cv2.imshow('Original', img)
cv2.imshow('Gray Image', imgGray)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Конвертация в градации серого уменьшает размер данных в 3 раза (1 канал вместо 3)
- HSV цветовое пространство лучше подходит для детектирования цветов
- Порядок каналов в OpenCV - BGR, а не RGB (важно при работе с другими библиотеками)
3.2 Размытие изображения (Gaussian Blur)
Используемые методы:
cv2.GaussianBlur(src, ksize, sigmaX)- гауссово размытиеsrc- исходное изображениеksize- размер ядра (кортеж (width, height)), должен быть нечетнымsigmaX- стандартное отклонение по оси X (0 - автоматический расчет)
Практический пример:
import cv2
import numpy as np
# Чтение изображения
img = cv2.imread('resources/lena.png')
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Применение гауссова размытия
imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 0) # (7, 7) - размер ядра
# Отображение результатов
cv2.imshow('Gray Image', imgGray)
cv2.imshow('Blur Image', imgBlur)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Размер ядра (ksize) влияет на степень размытия: чем больше ядро, тем сильнее размытие
- Размер ядра должен быть нечетным (3, 5, 7, 9...) для симметричного размытия
- Размытие уменьшает шум и высокочастотные детали, что полезно перед детектированием границ
- Ядро 3×3 дает легкое размытие, 7×7 - сильное размытие
3.3 Детектирование границ (Canny Edge Detection)
Используемые методы:
cv2.Canny(image, threshold1, threshold2)- детектирование границ методом Cannyimage- исходное изображение (лучше использовать размытое изображение)threshold1- нижний порог градиентаthreshold2- верхний порог градиента- Соотношение threshold2/threshold1 обычно 2:1 или 3:1
Практический пример:
import cv2
# Чтение изображения
img = cv2.imread('resources/lena.png')
# Детектирование границ
imgCanny = cv2.Canny(img, 100, 100) # Базовые пороги
# Улучшенная версия с размытием перед детектированием
imgBlur = cv2.GaussianBlur(img, (7, 7), 0)
imgCannyEnhanced = cv2.Canny(imgBlur, 50, 150)
# Отображение результатов
cv2.imshow('Original', img)
cv2.imshow('Canny Basic', imgCanny)
cv2.imshow('Canny Enhanced', imgCannyEnhanced)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Алгоритм Canny использует градиенты яркости для нахождения границ
- Низкие пороги (50, 150) дают больше границ, высокие (200, 300) - меньше границ
- Размытие перед детектированием уменьшает шум и ложные границы
- Результат детектирования - бинарное изображение (0 и 255)
Урок 4: Морфологические операции
4.1 Дилатация (утолщение границ)
Используемые методы:
cv2.dilate(src, kernel, iterations)- дилатация изображенияsrc- исходное изображение (обычно результат Canny)kernel- структурирующий элемент (матрица из единиц)iterations- количество итераций (степень дилатации)
np.ones(shape, dtype)- создание матрицы из единицshape- размер матрицы (высота, ширина)dtype- тип данных (np.uint8 для изображений)
Практический пример:
import cv2
import numpy as np
# Чтение изображения
img = cv2.imread('resources/lena.png')
imgCanny = cv2.Canny(img, 100, 100)
# Создание ядра для дилатации
kernel = np.ones((5, 5), np.uint8) # Матрица 5x5 из единиц
# Применение дилатации
imgDilation = cv2.dilate(imgCanny, kernel, iterations=1)
# Усиленная дилатация
imgDilationStrong = cv2.dilate(imgCanny, kernel, iterations=3)
# Отображение результатов
cv2.imshow('Canny Image', imgCanny)
cv2.imshow('Dilation (1 iteration)', imgDilation)
cv2.imshow('Dilation (3 iterations)', imgDilationStrong)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Дилатация "раздувает" белые области на бинарном изображении
- Размер ядра влияет на радиус "раздувания" на каждой итерации
- Количество итераций определяет степень дилатации
- Полезно для соединения разорванных границ и заполнения маленьких дыр
4.2 Эрозия (утончение границ)
Используемые методы:
cv2.erode(src, kernel, iterations)- эрозия изображения- Параметры аналогичны функции дилатации
- Эффект противоположен дилатации - "сжигает" края белых областей
Практический пример:
import cv2
import numpy as np
# Чтение изображения
img = cv2.imread('resources/lena.png')
imgCanny = cv2.Canny(img, 100, 100)
kernel = np.ones((5, 5), np.uint8)
# Применение дилатации
imgDilation = cv2.dilate(imgCanny, kernel, iterations=1)
# Применение эрозии к результату дилатации
imgEroded = cv2.erode(imgDilation, kernel, iterations=1)
# Отображение результатов
cv2.imshow('Canny Image', imgCanny)
cv2.imshow('Dilation Image', imgDilation)
cv2.imshow('Eroded Image', imgEroded)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Эрозия уменьшает белые области на бинарном изображении
- Эффективна для удаления мелких шумов и изолированных пикселей
- При последовательном применении дилатации и эрозии получается операция "открытия"
- При последовательном применении эрозии и дилатации получается операция "закрытия"
- Эти операции являются базовыми в математической морфологии
Урок 5: Изменение размера и обрезка изображений
5.1 Изменение размера изображения
Используемые методы:
cv2.resize(src, dsize, fx, fy, interpolation)- изменение размера изображенияsrc- исходное изображениеdsize- целевой размер (ширина, высота)fx, fy- коэффициенты масштабирования (альтернатива dsize)interpolation- метод интерполяции (по умолчанию cv2.INTER_LINEAR)
img.shape- получение размеров изображения- Возвращает кортеж (высота, ширина, количество каналов)
- Для градаций серого: (высота, ширина)
Практический пример:
import cv2
# Чтение изображения
img = cv2.imread('resources/lambo.png')
# Получение и вывод размеров изображения
print("Размер исходного изображения:", img.shape) # (высота, ширина, каналы)
# Изменение размера (ширина, высота)
imgResize = cv2.resize(img, (300, 200)) # Новые размеры: ширина=300, высота=200
# Увеличение размера (может привести к потере качества)
# imgResize = cv2.resize(img, (1000, 500))
# Проверка нового размера
print("Размер измененного изображения:", imgResize.shape)
# Отображение результатов
cv2.imshow('Original Image', img)
cv2.imshow('Resized Image', imgResize)
cv2.waitKey(0)
cv2.destroyAllWindows()
- В OpenCV порядок размеров: сначала ширина, потом высота (в отличие от shape)
- Методы интерполяции:
cv2.INTER_LINEAR- билинейная (по умолчанию, хороша для уменьшения)cv2.INTER_CUBIC- бикубическая (качественная для увеличения)cv2.INTER_NEAREST- ближайший сосед (быстро, но низкое качество)
- Увеличение размера не добавляет новой информации, только интерполирует существующую
- Соотношение сторон может измениться, что приведет к искажению изображения
5.2 Обрезка изображения
Используемые методы:
- Индексирование массивов NumPy:
img[y1:y2, x1:x2]y1:y2- диапазон по вертикали (высота)x1:x2- диапазон по горизонтали (ширина)- Важно: сначала идет координата y (строки), потом x (столбцы)
Практический пример:
import cv2
# Чтение изображения
img = cv2.imread('resources/lambo.png')
# Обрезка изображения [начало_высоты:конец_высоты, начало_ширины:конец_ширины]
imgCropped = img[0:200, 200:500] # [y1:y2, x1:x2]
# Визуализация точек обрезки на исходном изображении
img_with_rect = img.copy()
cv2.rectangle(img_with_rect, (200, 0), (500, 200), (0, 255, 0), 2)
cv2.putText(img_with_rect, "Область обрезки", (220, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# Отображение результатов
cv2.imshow('Original Image with Crop Area', img_with_rect)
cv2.imshow('Cropped Image', imgCropped)
cv2.waitKey(0)
cv2.destroyAllWindows()
- В OpenCV начало координат (0,0) находится в левом верхнем углу
- Ось X идет вправо, ось Y идет вниз
- Индексирование использует систему координат NumPy: сначала строки (y), потом столбцы (x)
- Обрезка не изменяет исходное изображение, создает новое
- Размеры обрезанного изображения: (y2-y1, x2-x1, каналы)
Урок 6: Рисование фигур и текста на изображениях
6.1 Создание изображений и рисование базовых фигур
Используемые методы:
np.zeros(shape, dtype)- создание черного изображенияshape- размеры изображения (высота, ширина, каналы)dtype- тип данных (np.uint8 для 8-битных изображений)
cv2.line(img, pt1, pt2, color, thickness)- рисование линииpt1, pt2- начальная и конечная точки (x, y)color- цвет в формате BGR (255, 0, 0) для синегоthickness- толщина линии
cv2.rectangle(img, pt1, pt2, color, thickness)- рисование прямоугольникаpt1- верхний левый угол (x1, y1)pt2- нижний правый угол (x2, y2)thickness = cv2.FILLEDдля заполнения прямоугольника
cv2.circle(img, center, radius, color, thickness)- рисование кругаcenter- центр круга (x, y)radius- радиус круга в пикселях
Практический пример:
import cv2
import numpy as np
# Создание черного изображения (512x512 пикселей, 3 канала)
img = np.zeros((512, 512, 3), np.uint8)
# Рисование линии (изображение, начальная точка, конечная точка, цвет, толщина)
cv2.line(img, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3) # Зеленая диагональ
# Рисование прямоугольника (изображение, верхний левый угол, нижний правый угол, цвет, толщина)
cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), 2) # Красный прямоугольник с контуром
# Заполненный прямоугольник
cv2.rectangle(img, (300, 0), (512, 150), (255, 0, 0), cv2.FILLED) # Синий заполненный прямоугольник
# Рисование круга (изображение, центр, радиус, цвет, толщина)
cv2.circle(img, (450, 50), 30, (255, 255, 0), 5) # Голубой круг с контуром
# Отображение результата
cv2.imshow('Drawing Shapes', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Цвета в OpenCV задаются в формате BGR, а не RGB
- Толщина -1 или cv2.FILLED означает заполнение фигуры
- Координаты точек задаются как (x, y), где (0,0) - левый верхний угол
- img.shape[1] - ширина изображения, img.shape[0] - высота
- Все функции рисования изменяют исходное изображение
6.2 Добавление текста на изображения
Используемые методы:
cv2.putText(img, text, org, fontFace, fontScale, color, thickness)- добавление текстаtext- текстовая строка для отображенияorg- начальная точка текста (нижний левый угол первого символа)fontFace- тип шрифта:cv2.FONT_HERSHEY_SIMPLEX- простой пропорциональный шрифтcv2.FONT_HERSHEY_PLAIN- компактный шрифтcv2.FONT_HERSHEY_COMPLEX- более сложный шрифт
fontScale- масштаб шрифта (1.0 = нормальный размер)thickness- толщина штрихов символов
Практический пример:
import cv2
import numpy as np
# Создание черного изображения
img = np.zeros((512, 512, 3), np.uint8)
# Добавление текста с разными параметрами
cv2.putText(img, "OpenCV", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 255, 255), 3)
cv2.putText(img, "Font Scale 0.5", (100, 150), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
cv2.putText(img, "Font Scale 2.0", (100, 200), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 0, 255), 2)
cv2.putText(img, "FONT_HERSHEY_PLAIN", (100, 250), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 255), 2)
cv2.putText(img, "Thickness Demo", (100, 300), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 0), 1)
cv2.putText(img, "Thickness 5", (100, 350), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 5)
# Отображение результата
cv2.imshow('Text on Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Начальная точка (org) определяет позицию нижнего левого угла первого символа
- fontScale влияет на размер шрифта: 1.0 = стандартный размер
- thickness влияет на жирность шрифта
- Различные шрифты имеют разную читаемость и внешний вид
- Текст добавляется поверх существующих элементов изображения
- Для русских символов могут потребоваться дополнительные настройки или использование PIL
Урок 7: Перспективные преобразования и объединение изображений
7.1 Изменение перспективы (Bird Eye View)
Используемые методы:
cv2.getPerspectiveTransform(src, dst)- вычисление матрицы перспективного преобразованияsrc- координаты четырех точек в исходном изображении (numpy массив)dst- координаты четырех точек в целевом изображении (numpy массив)- Возвращает матрицу преобразования 3×3
cv2.warpPerspective(src, M, dsize)- применение перспективного преобразованияM- матрица преобразования от getPerspectiveTransformdsize- размер выходного изображения (ширина, высота)
Практический пример:
import cv2
import numpy as np
# Чтение изображения с картой
img = cv2.imread('resources/cards.jpg')
# Определение четырех угловых точек карты на исходном изображении (координаты подбираются вручную)
# Порядок точек: верхний левый, верхний правый, нижний левый, нижний правый
pts1 = np.float32([[111, 219], [287, 188], [154, 482], [352, 440]])
# Определение целевых точек для результата (прямоугольник стандартных размеров)
width, height = 250, 350 # Стандартные размеры игральной карты
pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
# Получение матрицы преобразования перспективы
matrix = cv2.getPerspectiveTransform(pts1, pts2)
print("Матрица преобразования:")
print(matrix)
# Применение преобразования перспективы
imgOutput = cv2.warpPerspective(img, matrix, (width, height))
# Визуализация исходных точек на оригинальном изображении
img_with_points = img.copy()
for i, point in enumerate(pts1):
x, y = int(point[0]), int(point[1])
cv2.circle(img_with_points, (x, y), 8, (0, 0, 255), cv2.FILLED)
cv2.putText(img_with_points, f"Point {i+1}", (x+10, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# Отображение результатов
cv2.imshow('Original Image with Points', img_with_points)
cv2.imshow('Warped Image (Bird Eye View)', imgOutput)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Порядок точек в pts1 и pts2 должен соответствовать друг другу
- Точки должны быть указаны в формате float32
- Для подбора точек можно использовать программы вроде Paint или специальные инструменты OpenCV
- Результат преобразования - прямоугольное изображение без перспективных искажений
- Применяется в сканерах документов, системах распознавания номеров, AR-приложениях
7.2 Объединение изображений
Простой метод (без масштабирования):
import cv2
import numpy as np
# Чтение изображений
img = cv2.imread('resources/lena.png')
# Горизонтальное объединение (требует одинаковой высоты)
imgHor = np.hstack((img, img)) # numpy.hstack для горизонтального стека
# Вертикальное объединение (требует одинаковой ширины)
imgVer = np.vstack((img, img)) # numpy.vstack для вертикального стека
# Отображение результатов
cv2.imshow('Horizontal Stack', imgHor)
cv2.imshow('Vertical Stack', imgVer)
cv2.waitKey(0)
cv2.destroyAllWindows()
Универсальный метод (с масштабированием и разными каналами):
import cv2
import numpy as np
def stackImages(scale, imgArray):
"""
Функция для объединения изображений с возможностью масштабирования
и обработки изображений с разным количеством каналов.
Args:
scale (float): Коэффициент масштабирования
imgArray (list): Массив изображений (может быть 2D массивом для сетки)
Returns:
numpy.ndarray: Объединенное изображение
"""
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range(0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2:
imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank] * rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None, scale, scale)
if len(imgArray[x].shape) == 2:
imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor = np.hstack(imgArray)
ver = hor
return ver
# Использование функции
img = cv2.imread('resources/lena.png')
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 0)
imgCanny = cv2.Canny(img, 100, 100)
# Создание сетки изображений 2x2
imgStack = stackImages(0.5, (
[img, imgGray],
[imgBlur, imgCanny]
))
# Отображение результата
cv2.imshow('Stacked Images Grid', imgStack)
cv2.waitKey(0)
cv2.destroyAllWindows()
- Простой метод (hstack/vstack) требует одинаковых размеров и количества каналов
- Универсальная функция stackImages автоматически:
- Масштабирует изображения
- Конвертирует градации серого в BGR для совместимости
- Поддерживает создание сеток изображений (2D массивы)
- Параметр scale позволяет уменьшать изображения для размещения большего количества в одном окне
- Функция обрабатывает изображения с разным количеством каналов (RGB и градации серого)
- Пригодно для отладки и визуализации промежуточных результатов обработки
Заключение по базовому курсу:
В этом учебном пособии мы рассмотрели основные функции OpenCV для работы с изображениями и видео. Полученные знания позволяют:
- Читать и отображать изображения и видео
- Применять базовые операции обработки (конвертация цветов, размытие, детектирование границ)
- Выполнять морфологические операции (дилатация, эрозия)
- Изменять размеры и обрезать изображения
- Рисовать геометрические фигуры и текст
- Преобразовывать перспективу и объединять изображения
Эти навыки являются фундаментом для более сложных задач компьютерного зрения, таких как детектирование объектов, распознавание лиц, трекинг движущихся объектов и создание приложений дополненной реальности.
ЧЕК-ЛИСТ ПО 1 ЧАСТИ: ОСНОВЫ OPEN CV
Установка и настройка среды
| ✓ | Задача |
|---|---|
| Установлен Python | |
| Установлен PyCharm Community Edition | |
| Настроены пути (PATH) для Python и PyCharm | |
| Создан виртуальный проект в PyCharm | |
Установлены необходимые библиотеки: opencv-python, numpy |
|
| Проведена проверка установки импортом библиотек и выводом версий |
Понимание базовых концепций изображений
| ✓ | Задача |
|---|---|
| Понимаю, что такое пиксель и как он представлен в цифровом виде | |
| Знаю разницу между типами изображений: | |
|
|
|
|
|
|
| Знаю стандартные разрешения: VGA (640×480), HD (1280×720), Full HD (1920×1080) | |
| Понимаю, что в OpenCV используется цветовое пространство BGR, а не RGB |
Работа с изображениями
| ✓ | Задача |
|---|---|
Могу загружать изображение с помощью cv2.imread() |
|
Могу отображать изображение с помощью cv2.imshow() |
|
Использую cv2.waitKey(0) для задержки отображения |
|
Знаю, как закрыть окна с помощью cv2.destroyAllWindows() |
|
| Проверяю успешность загрузки изображения (обработка случая, когда файл не найден) |
Работа с видео
| ✓ | Задача |
|---|---|
Могу создать объект для захвата видео с помощью cv2.VideoCapture() |
|
Знаю, как считывать кадры с помощью cap.read() |
|
Понимаю структуру возвращаемого значения (success, img) |
|
Использую цикл while для обработки видео покадрово |
|
| Знаю, как добавить выход из цикла по нажатию клавиши 'q' | |
Освобождаю ресурсы с помощью cap.release() после окончания работы |
Работа с веб-камерой
| ✓ | Задача |
|---|---|
Могу подключиться к веб-камере с помощью cv2.VideoCapture(0) |
|
| Знаю, как установить параметры камеры: | |
Ширина кадра cap.set(3, width) |
|
Высота кадра cap.set(4, height) |
|
Яркость cap.set(10, brightness) |
|
Проверяю успешность подключения камеры с помощью cap.isOpened() |
|
Применяю зеркальное отображение при необходимости cv2.flip(img, 1) |
Базовые функции обработки изображений
| ✓ | Задача |
|---|---|
| Конвертация цветовых пространств | |
Могу конвертировать BGR в градации серого cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
|
| Понимаю преимущества работы с изображениями в градациях серого | |
| Размытие изображений | |
Применяю гауссово размытие cv2.GaussianBlur(img, (ksize, ksize), sigmaX) |
|
| Знаю, что размер ядра должен быть нечетным (3, 5, 7...) | |
| Понимаю влияние размытия на качество детектирования границ | |
| Детектирование границ | |
Использую алгоритм Canny cv2.Canny(img, threshold1, threshold2) |
|
| Знаю, как подбирать оптимальные пороговые значения | |
| Понимаю, что размытие перед детектированием улучшает результат | |
| Морфологические операции | |
Создаю ядро для морфологических операций np.ones((5,5), np.uint8) |
|
Применяю дилатацию cv2.dilate(img, kernel, iterations) |
|
Применяю эрозию cv2.erode(img, kernel, iterations) |
|
| Понимаю практическое применение этих операций | |
Изменение размера и обрезка изображений
| ✓ | Задача |
|---|---|
Знаю, как получить размеры изображения img.shape |
|
Могу изменить размер изображения cv2.resize(img, (width, height)) |
|
| Понимаю разницу в порядке параметров (resize: ширина→высота; shape: высота→ширина) | |
Могу обрезать изображение с помощью индексации img[y1:y2, x1:x2] |
|
| Знаю особенности системы координат в OpenCV (начало в левом верхнем углу) |
Рисование на изображениях
| ✓ | Задача |
|---|---|
Могу создать черное изображение np.zeros((height, width, 3), np.uint8) |
|
Рисую линии cv2.line(img, pt1, pt2, color, thickness) |
|
Рисую прямоугольники cv2.rectangle(img, pt1, pt2, color, thickness) |
|
Рисую заполненные прямоугольники (thickness=cv2.FILLED или -1) |
|
Рисую окружности cv2.circle(img, center, radius, color, thickness) |
|
Добавляю текст cv2.putText(img, text, org, font, scale, color, thickness) |
|
| Знаю основные шрифты OpenCV: | |
|
|
|
|
|
Практические навыки
| ✓ | Задача |
|---|---|
| Создал проект с чтением изображения, применением базовых преобразований и отображением результатов | |
| Реализовал программу для захвата видео с веб-камеры с возможностью выхода по клавише 'q' | |
| Написал программу, которая рисует геометрические фигуры и текст на изображении | |
| Создал функцию для объединения изображений в одну визуализацию | |
| Реализовал базовую обработку изображения (серый → размытие → границы → дилатация) |
Понимание ключевых концепций
| ✓ | Задача |
|---|---|
| Понимаю систему координат в OpenCV (ось Y направлена вниз) | |
| Знаю, как работает цветовое пространство BGR в OpenCV | |
| Понимаю, что изображение в OpenCV — это NumPy массив | |
| Знаю, как правильно освобождать ресурсы после работы с видео и камерой | |
| Понимаю важность предварительной обработки изображений перед детектированием объектов |
Общие замечания для самопроверки
| ✓ | Задача |
|---|---|
Все импорты библиотек выполнены корректно (import cv2, import numpy as np) |
|
| Все окна OpenCV закрываются после завершения программы | |
| Проверяю существование файлов перед их чтением | |
| Обрабатываю возможные ошибки при работе с камерой | |
| Использую понятные имена переменных | |
| Добавляю комментарии к коду для объяснения ключевых шагов | |
| Протестировал все функции на разных изображениях | |
| Понимаю, как работают параметры в каждой функции OpenCV |
```
