OpenCV (Open Source Computer Vision Library) — это библиотека с открытым исходным кодом для работы с компьютерным зрением. Изначально она была написана на C++, но адаптирована для использования на Python, С, Java и MATLAB.
В OpenCV есть встроенные алгоритмы компьютерного зрения на основе машинного обучения в виде отдельных модулей с разной функциональностью. Вот некоторые из них:
- Core Functionality (основная функциональность) — определяет основные структуры данных и функции библиотеки, которые используются в других модулях.
- Image Processing (обработка изображений) — позволяет работать со статичными изображениями: простыми картинками в форматах PNG, JPG и других.
- Video Analysis (анализ видео) — используется для отслеживания движений объектов и работы с фоном.
- Camera Calibration and 3D Reconstruction (калибровка камеры и 3D-реконструкция) — работает с геометрией объектов, позволяя создавать их 3D-модели на основе нескольких изображений или видео.
- 2D Features Framework (фреймворк двумерных особенностей) — определяет фрагменты изображения, которые отличаются от других, запоминая их контуры, и может находить похожие среди них.
- Object Detection (обнаружение объектов) — находит объекты, например лица, автомобили, птиц и другое.
- High-level GUI (высокоуровневый графический интерфейс) — позволяет рисовать графические интерфейсы для выполнения простых операций.
- Video I/O (ввод и вывод видео) — позволяет считывать и обрабатывать видеофайлы.
Установка OpenCV
Скачать библиотеку можно с помощью инструментов вашей IDE или с помощью командной строки:
можно импортировать модуль и приступать к работе:
import cv2
Библиотека работает с изображениями как с NumPy-массивами. Если изображение в оттенках серого, то массив этот двумерный. Каждый пиксель в изображении представлен в виде числа 0 до 255, где 0 — чёрный, 255 — белый, а всё остальное — оттенки серого между ними.
Каждая пиксельная строка объединена в одномерный массив. Например, [255, 255, 77, 77, 77, 255, 255]. Это строка из семи пикселей: двух белых, трёх серых и ещё двух белых.
Каждая такая пиксельная строка объединена в массив второго уровня. Например:
В итоге получается вот такое изображение, только в 100 раз меньше:
Если изображение цветное, то потребуется трёхмерный массив. Цвет каждого пикселя описывает не одно, а сразу три числа от 0 до 255 — в соответствии с моделью RGB. Только красный и синий цвет переставлены местами, так что первое число отвечает за синий цвет, второе — за зелёный, третье — за красный: получается BGR.
Вот примеры пикселей разного цвета на языке OpenCV:
- [0, 0, 0] — чёрный.
- [255, 255, 255] — белый.
- [255, 0, 0] — синий.
- [0, 255, 0] — зелёный.
- [0, 0, 255] — красный.
- [0, 255, 255] — жёлтый.
- [203, 192, 255] — розовый.
Таблицу распространённых цветов в RGB можно посмотреть здесь. Только помните, что в OpenCV первый и третий цвета переставлены местами.
Как и в случае с изображениями в оттенках серого, массив следующего уровня объединяет строки пикселей, а верхнеуровневый массив — всё изображение.
Вот так в OpenCV будет выглядеть массив для изображения из девяти цветных пикселей:
само изображение в увеличении такое:
Чтение, режимы отображения и запись
Например, вот такое изображение:
Прочитаем изображение и откроем его в отдельном окне:
- cv2.imread — «читает» изображение и возвращает NumPy-массив, с которым библиотека может работать. В качестве аргумента получает полный или относительный путь к изображению.
- cv2.imshow — открывает изображение в отдельном окне операционной системы. Первым аргументом получает название окна, вторым — NumPy-массив, в нашем случае он хранится в переменной image.
- cv2.waitKey — если не указать эту функцию, то открытое окно тут же закроется. В качестве аргумента получает кнопку, которую нужно нажать, чтобы закрыть окно. Если указать 0, то окно закроется при нажатии любой кнопки.
Можно передать функции cv2.imread необязательный второй аргумент и выбрать режим отображения:
- cv2.IMREAD_COLOR (по умолчанию) — цветное отображение в формате RGB.
- cv2.IMREAD_GRAYSCALE — отображение в оттенках серого.
Таким образом, функцию cv2.imread можно использовать, чтобы обесцветить цветное изображение:
получится:
чтобы сохранить новое изображение в отдельный файл нужно использовать cv2.imwrite :
Первым аргументом функция принимает название нового файла с картинкой, вторым — NumPy-массив с данными изображения.
Изменение цвета пикселей
Для начала получим доступ к пикселю. Для этого обратимся к нему по координатам. Сначала указываем координаты ширины, потом — высоты. Например:
изменим цвет пикселя, для этого обратимся к нему по координатам и сделаем его синим. Помним, что синий и красный переставлены местами:
image[0, 0] = [255, 0, 0]
Если открыть изменённое изображение, то в правом верхнем углу вы увидите чёрную точку размером с один пиксель.
- image.shape[0] — высота изображения в пикселях.
- image.shape[1] — ширина изображения в пикселях.
Используя циклы, можно изменять цвет сразу множества пикселей. Например, нарисовать для картинки чёрную рамку шириной 10 пикселей.
Внешние циклы перебирают каждый пиксель по горизонтали (первый) и вертикали (второй), а внутренние циклы идут от краёв к центру изображения и на каждом витке перекрашивают в чёрный по пикселю.
получается:
Чтобы изменить размер изображения, используйте функцию cv2.resize. Уменьшим нашу картинку в два раза:
- image — NumPy-массив изображения, размер которого мы изменяем.
- (399, 368) — ширина и высота нового изображения.
- cv2.INTER_AREA — метод интерполяции, то есть алгоритм, по которому OpenVC выбирает, в какие цвета красить пиксели.
Есть несколько методов интерполяции, но в большинстве случаев достаточно двух из них:
- cv2.INTER_LINEAR — для увеличения изображения. Используется по умолчанию, если не указано иное.
- cv2.INTER_AREA — для уменьшения картинки.
Чтобы сохранять пропорции изображения и каждый раз не высчитывать их вручную, используйте данные, полученные с помощью метода shape:
Чтобы обрезать изображение, укажите диапазоны координат, в которых хотите оставить изображение, — сначала высоту, потом ширину. Например:
Чтобы повернуть картинку, используйте сразу две функции:
Функция cv2.getRotationMatrix2D задаёт матрицу, по которой будет повёрнуто изображение. Она получает следующие аргументы:
- (399, 368) — координаты точки, вокруг которой происходит поворот.
- 60 — угол поворота в градусах.
- 0.8 — коэффициент масштабирования. В нашем случае мы уменьшаем изображение, чтобы части логотипа не вышли за край.
Функция cv2.warpAffine непосредственно поворачивает изображение. Она получает следующие аргументы:
- image — само изображение.
- matrix — матрица, созданная функцией cv2.getRotationMatrix2D.
- (image.shape[1], image.shape[0]) — размеры итогового изображения. В нашем случае мы оставляем те же, что были.
Отображение координат точки
import cv2
# функция реакции на нажатие левой или правой кнопки мыши def click_event(event, x, y, flags, params):
# если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN:
# выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}')
b = img[y, x, 0]
g = img[y, x, 1]
r = img[y, x, 2]
print(f'BGR-код точки: {b}, {g}, {r}\n')
# рисуем координаты точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, f'{x}, {y}', (x, y),
font, 1, (0, 0, 0), 2)
cv2.imshow('image', img)
# если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN:
# узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0]
g = img[y, x, 1]
r = img[y, x, 2]
# выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}')
print(f'BGR-код точки: {b}, {g}, {r}\n')
# рисуем BGR-код точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, f'{b}, {g}, {r}', (x, y),
font, 1, (0, 0, 0), 2)
cv2.imshow('image', img)
# основной сценарий if __name__ == "__main__":
img = cv2.imread('logo.jpg', 1)
cv2.imshow('image', img)
# устанавливаем реакцию на действия мыши и вызываем функцию click_event cv2.setMouseCallback('image', click_event)
cv2.waitKey(0)
В итоге: