Интеграция OpenCV и библиотеки NumPy для анализа данных

Раздел: Машинное обучение -> OpenCV с NumPy

Основы работы OpenCV и NumPy

OpenCV (Open Source Computer Vision Library) и NumPy являются фундаментальными библиотеками для обработки изображений и научных вычислений в Python. Изображение в OpenCV представляется как многомерный массив NumPy (ndarray), что позволяет использовать все возможности NumPy для манипуляции данными. Основное эффективное решение - чтение изображения с последующей обработкой как массива.


import cv2
import numpy as np

# Чтение изображения
img = cv2.imread('photo.jpg')
# img - это массив NumPy shape (height, width, channels)

# Доступ к пикселю (строка 100, столбец 200)
pixel = img[100, 200]
print(pixel)  # [B G R]

# Изменение цвета пикселя
img[100, 200] = [255, 0, 0]  # синий

# Изменение целой области (квадрат 50x50)
img[50:100, 50:100] = [0, 255, 0]  # зеленый

# Сохранение измененного изображения
cv2.imwrite('result.jpg', img)

Opencv python numpy (opencv и numpy в python)

Пояснение:

Функция cv2.imread() возвращает массив NumPy. Индексация осуществляется по строкам (y) и столбцам (x). Каналы идут в порядке BGR (синий, зеленый, красный).

Возможные проблемы:

  • Путь к файлу неверный: cv2.imread() не вызывает ошибку, а возвращает None. Проверять img is None.
  • Изменение изображения без копирования: операции изменяют исходный массив. Для копии используйте img.copy().

Как преобразовать цветовое пространство изображения?

OpenCV предоставляет функцию cv2.cvtColor(). Поскольку данные хранятся в NumPy, преобразование выполняется быстро.


gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

Типичная ошибка: забыть, что в OpenCV изображение в BGR, а не RGB. При отображении через matplotlib (который ожидает RGB) цвета будут искажены. Решение: перед отображением конвертировать: img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).

Как выполнить поэлементные операции над изображениями?

NumPy позволяет складывать, вычитать, умножать изображения поэлементно. Однако OpenCV предоставляет функции cv2.add(), cv2.subtract() и т.д., которые корректно обрабатывают переполнение (насыщение), в отличие от прямого numpy сложения (которое делает wrap around).


img1 = cv2.imread('a.jpg')
img2 = cv2.imread('b.jpg')
# Прямое сложение (wrap around)
sum_wrap = img1 + img2
# OpenCV сложение (насыщение)
sum_sat = cv2.add(img1, img2)

Если изображения разных размеров, их необходимо привести к одному размеру с помощью cv2.resize() или обрезать.

Как выделить область интереса с помощью маски?

Битовые операции (AND, OR, XOR, NOT) применяются к бинарным маскам для выделения областей. Маска - это также NumPy массив.


mask = np.zeros(img.shape[:2], dtype=np.uint8)
mask[100:300, 200:400] = 255
masked = cv2.bitwise_and(img, img, mask=mask)

Маска должна быть одноканальной (grayscale) и иметь тот же размер, что и изображение. Тип данных - uint8.

Как построить гистограмму изображения?

OpenCV предоставляет cv2.calcHist(). Результат - массив NumPy, который можно визуализировать с помощью matplotlib.


hist = cv2.calcHist([img], [0], None, [256], [0,256])
# или с использованием NumPy:
hist_np, bins = np.histogram(img.ravel(), 256, [0,256])

Гистограмма строится для каждого канала отдельно. Для цветных изображений часто строят гистограмму для яркости (значение V из HSV).

Как применить пороговое преобразование для бинаризации?

Функция cv2.threshold() возвращает пороговое значение и бинарное изображение. Можно использовать адаптивные методы, такие как cv2.adaptiveThreshold().


ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

Порог должен быть выбран вручную или методом Оцу (cv2.THRESH_OTSU). Адаптивный порог лучше для неравномерного освещения.

Как найти контуры объектов на изображении?

После бинаризации можно найти контуры с помощью cv2.findContours(). Контуры представлены как список массивов NumPy.


contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0,255,0), 2)

OpenCV версии 3+ возвращает два значения, в старых версиях - три. Для совместимости используйте contours, _ = cv2.findContours(...), если иерархия не нужна. Важно, что функция изменяет входное изображение, поэтому рекомендуется передавать копию.

Расширенные примеры использования OpenCV и NumPy

Пример 1: Покадровая обработка видео с изменением цветового баланса

Захватывается видео с камеры или из файла, каждый кадр преобразуется в оттенки серого, а затем цветной канал синтезируется обратно с изменением яркости. Используется NumPy для манипуляции массивами.

Пример

import cv2
import numpy as np

cap = cv2.VideoCapture(0)  # или файл
while True:
    ret, frame = cap.read()
    if not ret:
        break
    # Изменение яркости зеленого канала
    frame[:,:,1] = cv2.add(frame[:,:,1], 50)  # увеличиваем зеленый
    cv2.imshow('Frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
Результат: видео с усиленным зеленым оттенком. Кадры обрабатываются со скоростью, близкой к встроенной частоте кадров.

Пример 2: Мозаичное пикселизация изображения

Изображение делится на блоки, каждый блок усредняется, создавая эффект мозаики (пикселизации). Манипуляции проводятся через NumPy.

Пример

import cv2
import numpy as np

img = cv2.imread('photo.jpg')
h, w = img.shape[:2]
block_size = 20
for y in range(0, h, block_size):
    for x in range(0, w, block_size):
        block = img[y:y+block_size, x:x+block_size]
        mean = cv2.mean(block)[:3]  # среднее BGR
        img[y:y+block_size, x:x+block_size] = mean
cv2.imwrite('pixelated.jpg', img)
Результат: изображение с квадратными блоками, каждый блок залит средним цветом исходной области.

Пример 3: Линейное смешивание двух изображений с маской прозрачности

Используется cv2.addWeighted() для смешивания, но добавляется управление через маску, созданную с помощью NumPy.

Пример

import cv2
import numpy as np

img1 = cv2.imread('a.jpg')
img2 = cv2.imread('b.jpg')
# Приводим изображения к одному размеру
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
# Маска градиента
mask = np.zeros(img1.shape[:2], dtype=np.float32)
mask[:, :img1.shape[1]//2] = 1.0
mask[:, img1.shape[1]//2:] = np.linspace(1, 0, img1.shape[1]//2)
# Смешивание с использованием маски
blended = ((img1 * mask[:,:,np.newaxis]) + (img2 * (1 - mask[:,:,np.newaxis]))).astype(np.uint8)
cv2.imwrite('blended.jpg', blended)
Результат: плавный переход от первого изображения ко второму, управляемый маской градиента.

OpenCV и NumPy в Python - comments

En
Opencv python numpy (python)