Предыдущий портал:
«Обработка изображений Python OpenCV (1): начало работы»
«Обработка изображений Python OpenCV (5): геометрическое преобразование изображений»
«Обработка изображений Python OpenCV (6): пороговое значение изображения»
1. Введение
Во-первых, сначала нужно объяснить термины: что такое сглаживание изображений?
Из буквального смысла кажется, что сглаживание изображения похоже на то, что изображение скользит.
эммммммммммммммм. . . .
На самом деле, нет никакой связи между полцентом и технологией сглаживания изображений, обычно называемой технологией фильтрации изображений (вы можете немного почувствовать, когда увидите это название).
Каждое изображение содержит определенную степень шума, и под шумом можно понимать случайные изменения значений оттенков серого, вызванные одной или несколькими причинами, например шум, вызванный хаотичностью потока фотонов и так далее.
Технология сглаживания изображения или технология фильтрации изображения используются для борьбы с шумом на изображении, Среди них процесс сглаживания изображения, который может поддерживать края, стал центром всеобщего внимания.
Это не ерунда,обработка картинки для уменьшения шума,и в результате все изображение как слой водяного тумана на стекле.В чем смысл этого шумоподавления.
В этой статье будут представлены 4 алгоритма сглаживания изображений, представленные в OpenCV:
- средний фильтр
- блочный фильтр
- фильтр Гаусса
- медианный фильтр
Давайте начнем смотреть один за другим :)
Сначала дайте программу для добавления шума в Марио, программа взята из блога мистера Янга:blog.CSDN.net/east mount/Ах…, полный код выглядит следующим образом:
import cv2 as cv
import numpy as np
# 读取图片
img = cv.imread("maliao.jpg", cv.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 加噪声
for i in range(5000):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
img[x, y, :] = 255
cv.imshow("noise", img)
# 图像保存
cv.imwrite("maliao_noise.jpg", img)
# 等待显示
cv.waitKey()
cv.destroyAllWindows()
Приведенная выше программа на самом деле случайным образом добавляет к изображению 5000 белых точек, и этот шум действительно достаточно велик.
2. Свертка 2D-изображений
Прежде чем вводить фильтрацию, давайте кратко представим свертку 2D-изображения.Свертка изображения на самом деле является фильтрацией изображения.
При фильтрации изображения можно использовать различные фильтры нижних частот (ФНЧ), фильтры высоких частот (ФВЧ) и т. д. для фильтрации изображения.
Фильтр нижних частот (ФНЧ) помогает удалить шум, но может размыть изображение.
Фильтр верхних частот (HPF) помогает найти края изображения.
OpenCV предоставляет нам функциюfilter2D()для свертки ядра с изображением.
Мы пытаемся усреднить фильтр изображения, ядро среднего фильтра 5 x 5 выглядит следующим образом:
Конкретные операции заключаются в следующем:
Мы сохраняем это ядро на одном пикселе, добавляем все 25 пикселей ниже этого ядра, берем среднее значение и заменяем центральный пиксель новым средним значением. Эта операция будет продолжена для всех пикселей изображения, полный пример кода выглядит следующим образом:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 读取图片
img = cv.imread("maliao_noise.jpg", cv.IMREAD_UNCHANGED)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
kernel = np.ones((5,5),np.float32)/25
dst = cv.filter2D(rgb_img, -1, kernel)
titles = ['Source Image', 'filter2D Image']
images = [rgb_img, dst]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
Видно, что шум действительно убирается, то есть картинка становится размытой.
3. Средний фильтр
Средняя фильтрация означает, что значение пикселя в любой точке является средним значением окружающих N * M значений пикселей.
Фактически, средний фильтр и приведенный выше пример свертки изображения делают одно и то же, я просто используюfilter2D()Этот метод вручную завершает среднюю фильтрацию.Фактически, OpenCV предоставляет нам специальный метод средней фильтрации.Студенты, которые не поняли предыдущую свертку изображения, могут повторить среднюю фильтрацию.Я стараюсь сделать это понятным.
Нарисуем картинку:
Значение в красном поле посередине представляет собой сумму пикселей в окружающих 25 областях сетки, деленную на 25. Формула выглядит следующим образом:
Дабы не лениться, все значения пикселей в сетке записываются как 1, ведь n/n всегда равно 1, прошу похвалить мою смекалку.
Приведенная выше матрица 5 * 5 называется ядром.Для пикселей в исходном изображении ядро используется для обработки результирующего изображения.
Мы можем настроить размер этого ядра, например, 5 * 5, 3 * 3, 10 * 10 и т. д. Конкретное определение зависит от лечебного эффекта.
OpenCV дает мнеblur()Метод используется для реализации фильтрации среднего, исходная функция выглядит следующим образом:
def blur(src, ksize, dst=None, anchor=None, borderType=None)
- kSize: Параметр ядра - это фактически матрица, которая умножается при свертывании изображения. Как вычислить конкретную свертку? Их много в Интернете, поэтому я не буду приводить его здесь. Полученное изображение размыто, а изображение на самом деле отсутствует (исходное изображение - параметр ядра + 1) ^ 2 ячейки в соответствии с исходной пропорцией.
- привязка: тип точки, то есть точка привязки, имеет значение по умолчанию Point(-1, -1) , когда координата отрицательная, это означает центр ядра.
- borderType: тип Int, используемый для вывода определенного режима границы для пикселей за пределами изображения, со значением по умолчанию BORDER_DEFAULT.
Далее приведен пример кода для фильтрации среднего значения:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片
img = cv.imread("maliao_noise.jpg", cv.IMREAD_UNCHANGED)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 均值滤波
blur_img = cv.blur(rgb_img, (3, 3))
# blur_img = cv.blur(img, (5, 5))
# blur_img = cv.blur(img, (10, 10))
# blur_img = cv.blur(img, (20, 20))
titles = ['Source Image', 'Blur Image']
images = [rgb_img, blur_img]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
Эффект от этого шумоподавления кажется не таким хорошим, как эффект шумоподавления предыдущей 2D-свертки, но изображение получается более четким, потому что в этом примере я использовал ядро меньшего размера 3*3, и, кстати, я также пробовал большое ядро, такое как ядро 10*10 или ядро 20*20, закомментированное в коде, в реальном времени доказано, что чем больше ядро, тем лучше эффект шумоподавления, но, наоборот, изображение будет размытым.
4. Фильтрация ящиков
Ядра блочной фильтрации и средней фильтрации в основном одинаковы, разница заключается в том, требуется ли нормализация или нет.
Что такое нормализационная обработка, поговорим о ней позже, давайте посмотрим на исходную функцию блочной фильтрации:
def boxFilter(src, ddepth, ksize, dst=None, anchor=None, normalize=None, borderType=None)
- источник: Исходное изображение.
- ddepth: тип Int, глубина целевого изображения, обычно -1 означает, что оно соответствует исходному изображению.
- kSize: параметр ядра.
- DST: SRC выводит тот же размер и тип изображения.
- привязка: тип точки, то есть точка привязки, со значением по умолчанию Point(-1, -1) .
- normalize: тип Int, указывающий, следует ли нормализовать целевое изображение.
Когда normalize имеет значение true, необходимо выполнить обработку усреднения.
Когда normalize имеет значение false, процесс усреднения не выполняется.Фактически вычисляется сумма окружающих пикселей.Это легко переполнить, а переполнение белое, и соответствующее значение пикселя равно 255.
Полный пример кода выглядит следующим образом:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片
img = cv.imread('maliao_noise.jpg')
source = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 方框滤波
result = cv.boxFilter(source, -1, (5, 5), normalize = 1)
# 显示图形
titles = ['Source Image', 'BoxFilter Image']
images = [source, result]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
Когда мы устанавливаем для свойства normalize значение 0, нормализация не выполняется, и результат становится следующим:
5. Фильтр Гаусса
Чтобы преодолеть недостаток простого метода локального усреднения (размытие изображения), было предложено множество алгоритмов локального сглаживания, сохраняющих края и детали. Их отправные точки сосредоточены на том, как выбрать размер, форму и направление района, среднее значение параметров и весовой коэффициент каждого магазина в районе.
В методе фильтрации Гаусса ядро свертки фактически заменяется ядром Гаусса, так что же такое ядро Гаусса?
Короче говоря, это ящик или ящик. Первоначально веса в каждом ящике были равны, и все в конце концов взяли среднее. Теперь это стало распределением по Гауссу. Вес в центре ящика самый большой, а остальные поля основаны на расстоянии.Расстояние между центральными элементами уменьшается, образуя холм Гаусса, поэтому полученное значение становится средневзвешенным.
На рисунке ниже показано ядро Гаусса для полей 3*3 и 5*5.
Фильтрация по Гауссу выполняется в OpenCV с помощьюGaussianBlur()метод, его исходная функция заключается в следующем:
def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
- sigmaX: Указывает отклонение в направлении X.
Здесь необходимо отметить размер ядра ksize.В ядре Гаусса ядро (N, N) должно быть нечетным числом, а дисперсия в направлении X в основном контролирует вес.
Полный пример кода выглядит следующим образом:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片
img = cv.imread('maliao_noise.jpg')
source = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 方框滤波
result = cv.GaussianBlur(source, (3, 3), 0)
# 显示图形
titles = ['Source Image', 'GaussianBlur Image']
images = [source, result]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
6. Медианная фильтрация
Граница размывается при шумоподавлении с использованием метода усреднения по окрестностям.
Медианный фильтр — это метод нелинейной обработки изображений, который может учитывать сохранение информации о границах при шумоподавлении.
Специфический метод медианной фильтрации состоит в том, чтобы выбрать окно W, содержащее нечетные точки, отсканируйте это окно на изображении, устраивайте пиксели, содержащиеся в окне в порядке возрастания или убывания уровня серого, и возьмите значение середины в середине, чтобы заменить Серая ценность точки.
На следующем рисунке показан процесс фильтрации одномерного окна:
В OpenCV, в основном, по телефонуmedianBlur()Для реализации медианной фильтрации его исходная функция выглядит следующим образом:
def medianBlur(src, ksize, dst=None)
Количество ядер для медианной фильтрации совпадает с количеством ядер для гауссовой фильтрации и должно быть нечетным числом, большим 1.
Пример кода выглядит следующим образом:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片
img = cv.imread('maliao_noise.jpg')
source = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 方框滤波
result = cv.medianBlur(source, 3)
# 显示图形
titles = ['Source Image', 'medianBlur Image']
images = [source, result]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
Хорошо видно, что медианный фильтр в настоящее время имеет наивысшую степень восстановления после шумоподавления исходного изображения.Помимо прямоугольников, есть также кресты, кружки и кольца для часто используемой графики медианного фильтра.Разные формы окон дают разные результаты. эффект фильтра.
Квадратные и круглые окна подходят для изображений объектов с длинными очертаниями, а крестообразные — для изображений с острыми углами.
Для некоторых сложных изображений с большей детализацией различные медианы фильтров можно использовать несколько раз.
7. Пример кода
Если вам нужно получить исходный код, вы можете ответить на «OpenCV» в общедоступной учетной записи, чтобы получить его.