Привет, Хабр! Это продолжение урока по библиотеке opencv в Python. Для тех, кто не читал первую и вторую часть, здесь: Часть 1 И Часть 2 , а всем остальным – приятного чтения!
Введение
В этой части мы рассмотрим арифметику изображений, разделение и объединение каналов, а также различные методы размытия.
Арифметика изображений
Надеюсь, все знают арифметические операции вроде сложения и вычитания, но при работе с изображениями нельзя забывать о типе данных.Например, у нас есть изображение RGB, пиксели которого попадают в диапазон [0,255].
Итак, что произойдет, если мы попытаемся прибавить 30 к пикселю с интенсивностью 250 или вычесть 100 из 70? Если бы мы использовали стандартные правила арифметики, мы получили бы 280 и -30 соответственно.
Однако если мы работаем с изображениями RGB, где значения пикселей представлены как 8-битное целое число без знака, то 280 и -30 не являются допустимыми значениями.
Чтобы понять, что произойдет, давайте посмотрим на строки кода ниже:
Как мы видим, сложение и вычитание можно выполнять с помощью функций opencv add и subtract соответственно, а также с помощью numpy. И результаты будут разными:print("opencv addition: {}".
format(cv2.add(np.uint8([250]), np.uint8([30])))) print("opencv subtract: {}".
format(cv2.subtract(np.uint8([70]), np.uint8([100])))) print("numpy addition: {}".
format(np.uint8([250]) + np.uint8([30]))) print("numpy subtract: {}".
format(np.uint8([70]) - np.uint8([71])))
opencv addition: 255
opencv subtract: 0
numpy addition: 24
numpy subtract: 255
OpenCV выполняет обрезку и гарантирует, что значения пикселей никогда не выходят за пределы диапазона [0,255].
В numpy все происходит немного по-другому.
Представьте себе обычные настенные часы, где вместо 60 стоит 255. Получается, что после достижения 255 следующим числом будет 0, а когда мы из меньшего числа вычитаем большее число, то после 0 (против часовой стрелки) будет 255. .
Разделение и объединение каналов
Как мы знаем, RGB-изображение состоит из красного, зеленого и синего компонентов.
А что, если мы захотим разделить изображение на соответствующие компоненты? Для этого в opencv есть специальная функция — Split(): image = cv2.imread('rectangles.png')
b, g, r = cv2.split(image)
cv2.imshow('blue', b)
cv2.imshow('green', g)
cv2.imshow('red', r)
Сначала загружаем изображение.
Чтобы проиллюстрировать, как работает эта функция, я взял следующее изображение:
Затем делим изображение на три канала и показываем каждый канал отдельно.
В результате работы этой функции будут отображены три изображения в оттенках серого:
Как мы видим, для каждого изображения каждого канала белым отображается только прямоугольник одного цвета.
Вот как будет выглядеть каждая деталь для девочки из предыдущих частей:
Как видите, красный канал очень светлый.
Это потому, что на нашем изображении очень сильно представлены оттенки красного.
Синий и зеленый каналы, наоборот, очень темные.
Это происходит потому, что в данном изображении этих цветов очень мало.
Чтобы объединить каналы вместе, достаточно использовать функцию merge(), которая принимает значения каналов: merge_image = cv2.merge([g,b,r])
cv2.imshow('merge_image', merge_image)
cv2.imshow('original', image)
cv2.waitKey(0)
Таким образом, мы получаем то же изображение, что и оригинал, за исключением того, что я поменял местами синий и зеленый каналы.
Размытие
Размытие — это когда более резкие области изображения теряют детализацию, в результате чего изображение становится менее четким.Opencv имеет следующие основные методы размытия: усреднение, гауссово и медианное.
Усреднение
Этот фильтр выполняет операцию свертки над изображением с определённым ядром, где свертка — это вычисление нового значения пикселя, учитывающего значения соседних пикселей.Ядро свертки представляет собой квадратную матрицу, где пикселю в центре этой матрицы затем присваивается среднее значение всех остальных пикселей, окружающих его.
Чтобы использовать это размытие, просто вызовите метод Blur(), который принимает изображение и кортеж, указывающий размер ядра: def averaging_blurring():
image = cv2.imread('girl.jpg')
img_blur_3 = cv2.blur(image, (3, 3))
img_blur_7 = cv2.blur(image, (7, 7))
img_blur_11 = cv2.blur(image, (11, 11))
Чем больше размер ядра, тем более размытым будет изображение:
Гауссовский
Размытие по Гауссу похоже на предыдущее размытие, за исключением того, что вместо простого среднего значения мы теперь используем взвешенное среднее, где соседние пиксели, находящиеся ближе к центральному пикселю, вносят больший вклад в среднее значение.
Конечным результатом является то, что наше изображение размыто более естественно:
Это размытие реализовано в opencv с помощью функции GaussianBlur(), которая принимает первые два аргумента так же, как и предыдущая функция, а третий аргумент задает стандартное отклонение ядра Гаусса.
Установив это значение равным 0, мы сообщаем opencv автоматически вычислять его в зависимости от размера нашего ядра: def gaussian_blurring():
image = cv2.imread('girl.jpg')
img_blur_3 = cv2.GaussianBlur(image, (3, 3), 0)
img_blur_7 = cv2.GaussianBlur(image, (7, 7), 0)
img_blur_11 = cv2.GaussianBlur(image, (11, 11), 0)
медиана
При медианном размытии центральный пиксель изображения заменяется медианой всех пикселей в области ядра, в результате чего это размытие наиболее эффективно при удалении шума в виде соли.
Для того, чтобы применить этот тип размытия, вам нужно вызвать функцию medianBlur() и передать туда два параметра: изображение и размер ядра: def median_blurring():
image = cv2.imread('girl.jpg')
img_blur_3 = cv2.medianBlur(image, 3)
img_blur_7 = cv2.medianBlur(image, 7)
img_blur_11 = cv2.medianBlur(image, 11)
В результате мы получаем следующее:
На этом данная часть завершается.
Код, как всегда, доступен по адресу github .
До скорой встречи:) Теги: #python #учебник #Обработка изображений #OpenCV
-
Как Создать Групповой Лист В Excel
19 Oct, 24 -
Ленц, Эмилий Христианович
19 Oct, 24 -
Azure-Iaas-Дайджест №7 (Май-Июнь)
19 Oct, 24 -
Sass-Архитектура Для Вашего Проекта
19 Oct, 24