Фильтрация в OpenCV: функции inRange(), medianBlur()
В уроке разберем понятие фильтрации, функцию inRange() для фильтрации, функцию medianBlur() для размытия в OpenCV. Сделаем фильтрацию с помощью ползунков.
Понятие фильтрации
Термин «фильтрация» применим к разным сферам, например, к физическим объектам и к информации. Мы используем фильтры для воды, чтобы очистить жидкость от примесей и различных бактерий.
Фильтрация — отделение нужного от ненужного. Мы будем отделять полезный сигнал от всех остальных.
Любое изображение является набором пикселей. Каждый пиксель задается определенным набором чисел. Подробнее про цветовые пространства читайте в статье. Чаще всего используются RGB пространства, то есть соотношение красного, зеленого и синего. Это соотношения задаются в диапазонах от 0 до 255.
Функция inRange()
Для фильтрации изображения используется функция вида inRange(img, l_s, r_s). Первый параметр — изменяемое изображение, а второй и третий — левая и правая граница пропускаемого цвета. Для границ мы будем использовать ползунки. Для задания каждой из границ потребуется 3 ползунка, так как у нас 3 канала в RGB. Всего нужно шесть ползунков.
Функция inRange() на выходе дает набор пикселей со значением либо 0, либо единица, т.е. цвет удовлетворяет заданным границам или не удовлетворяет.
На этом изображении введено ограничение только на пропускаемую красную составляющую. На примере пропускаем пиксели интенсивностью от 192 до 255 в красном цветовом канале:
Создание фильтра
Создаем окно настроек с 6 ползунками. Значение снимаем в цикле отображения изображения, где также отображаем отфильтрованное изображение:
import numpy as np
import cv2
# создаем пустую функцию
def nothing(args):pass
# создаем окно для отображения результата и бегунки
cv2.namedWindow("setup")
cv2.createTrackbar("b1", "setup", 0, 255, nothing)
cv2.createTrackbar("g1", "setup", 0, 255, nothing)
cv2.createTrackbar("r1", "setup", 0, 255, nothing)
cv2.createTrackbar("b2", "setup", 255, 255, nothing)
cv2.createTrackbar("g2", "setup", 255, 255, nothing)
cv2.createTrackbar("r2", "setup", 255, 255, nothing)
fn = "KOT.jpg" # путь к файлу с картинкой
img = cv2.imread(fn) # загрузка изображения
while True:
r1 = cv2.getTrackbarPos('r1', 'setup')
g1 = cv2.getTrackbarPos('g1', 'setup')
b1 = cv2.getTrackbarPos('b1', 'setup')
r2 = cv2.getTrackbarPos('r2', 'setup')
g2 = cv2.getTrackbarPos('g2', 'setup')
b2 = cv2.getTrackbarPos('b2', 'setup')
# собираем значения из бегунков в множества
min_p = (g1, b1, r1)
max_p = (g2, b2, r2)
# применяем фильтр, делаем бинаризацию
img_g = cv2.inRange(img, min_p, max_p)
cv2.imshow('img', img_g)
if cv2.waitKey(33) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Если мы выведем наложение исходного изображения и полученной выше маски, то получим изображение с пропущенными цветами:
Для создания такого фильтра необходимо использовать операцию bitwise_and(sr1, sr2, mask = mask). Операция является логическим умножением массива sr1 на массив sr2. Если ввести дополнительный параметр выходного массива mask = mask, то в качестве маски активируем полученный ранее «фильтрат».
Получаемый код:
import numpy as np
import cv2
def nothing(args):pass
cv2.namedWindow("setup")
cv2.createTrackbar("b1", "setup", 0, 255, nothing)
cv2.createTrackbar("g1", "setup", 0, 255, nothing)
cv2.createTrackbar("r1", "setup", 0, 255, nothing)
cv2.createTrackbar("b2", "setup", 255, 255, nothing)
cv2.createTrackbar("g2", "setup", 255, 255, nothing)
cv2.createTrackbar("r2", "setup", 255, 255, nothing)
fn = "KOT.jpg" # путь к файлу с картинкой
img = cv2.imread(fn) # загрузка изображения
while True:
r1 = cv2.getTrackbarPos('r1', 'setup')
g1 = cv2.getTrackbarPos('g1', 'setup')
b1 = cv2.getTrackbarPos('b1', 'setup')
r2 = cv2.getTrackbarPos('r2', 'setup')
g2 = cv2.getTrackbarPos('g2', 'setup')
b2 = cv2.getTrackbarPos('b2', 'setup')
min_p = (g1, b1, r1)
max_p = (g2, b2, r2)
img_mask = cv2.inRange(img, min_p, max_p)
img_m = cv2.bitwise_and(img, img, mask = img_mask) # создание фильтра
cv2.imshow('img', img_m)
if cv2.waitKey(33) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Функция сглаживания
Некоторые инструменты улучшают результаты работы фильтра. Это достигается с помощью первичной обработки изображения.
Мы можем получить более сглаженную маску. Для этого избавляем изображение от резких цветовых переходов через функцию medianBlur(img, blur). Функция принимает на вход размываемое изображение и параметр размытия.
Добавляем ползунок для размытия изображения:
import numpy as np
import cv2
def nothing(args):pass
cv2.namedWindow("setup")
cv2.namedWindow("setup2")
cv2.createTrackbar("b1", "setup", 0, 255, nothing)
cv2.createTrackbar("g1", "setup", 0, 255, nothing)
cv2.createTrackbar("r1", "setup", 0, 255, nothing)
cv2.createTrackbar("b2", "setup", 255, 255, nothing)
cv2.createTrackbar("g2", "setup", 255, 255, nothing)
cv2.createTrackbar("r2", "setup", 255, 255, nothing)
cv2.createTrackbar("blur", "setup2", 0, 10, nothing)
fn = "KOT.jpg" # путь к файлу с картинкой
img = cv2.imread(fn) # загрузка изображения
percent = 50
width = int(img.shape[1] * percent / 100)
height = int(img.shape[0] * percent / 100)
dim = (width, height)
img = cv2.resize(img, dim)
while True:
r1 = cv2.getTrackbarPos('r1', 'setup')
g1 = cv2.getTrackbarPos('g1', 'setup')
b1 = cv2.getTrackbarPos('b1', 'setup')
r2 = cv2.getTrackbarPos('r2', 'setup')
g2 = cv2.getTrackbarPos('g2', 'setup')
b2 = cv2.getTrackbarPos('b2', 'setup')
blur = cv2.getTrackbarPos('blur', 'setup2')
min_p = (g1,b1,r1)
max_p = (g2,b2,r2)
img_bl = cv2.medianBlur(img, 1+blur*2) # сглаживание изображения
img_mask = cv2.inRange(img_bl, min_p, max_p)
img_m = cv2.bitwise_and(img, img, mask = img_mask)
cv2.imshow('img', img_m)
if cv2.waitKey(33) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Изменяем настройки размытия и получаем изображение:
ЩОРд