Цель работы: Научиться реализовывать один из простых алгоритмов обработки изображений.
Задание:
- Реализовать программу согласно варианту задания. Базовый алгоритм, используемый в программе, необходимо реализовать в 2 вариантах: с использованием встроенных функций какой-либо библиотеки (OpenCV, PIL и др.) и нативно на Python с использованием циклов.
- Сравнить быстродействие реализованных вариантов.
- Сделать отчёт в виде readme на GitHub, там же должен быть выложен исходный код.
Отчёт должен содержать следующие пункты:
- Теоретическая база
- Описание разработанной системы (алгоритмы,принципы работы, архитектура)
- Результаты работы и тестирования системы(скриншоты,изображения, графики, закономерности)
- Выводы
- Использованные источники
Медиа́нный фи́льтр — один из видов цифровых фильтров, широко используемый в цифровой обработке сигналов и изображений для уменьшения уровня шума. Медианный фильтр является нелинейным КИХ-фильтром.
Значения отсчётов внутри окна фильтра сортируются в порядке возрастания (убывания); и значение, находящееся в середине упорядоченного списка, поступает на выход фильтра. В случае чётного числа отсчётов в окне выходное значение фильтра равно среднему значению двух отсчётов в середине упорядоченного списка. Окно перемещается вдоль фильтруемого сигнала, и вычисления повторяются.
Медианная фильтрация — эффективная процедура обработки сигналов, подверженных воздействию импульсных помех.
Требовалось реализовать медианный фильтр для устранения шумов, для реализации пункта 1 при реализации с помощью готовой библиотеки была выбрана библиотека PIL, предназначенная для работы с изображениями В данной библиотеке уже есть готовая реализация медианного фильтра.
В качестве образца для тестирования было выбрано следующее изображение:

Применить медианный фильтр с помощью библиотеки PIL не составило труда
im = Image.open('./balloons_noisy.png')
im.filter(ImageFilter.MedianFilter(3))
im.save('./balloons_noisy_pil_filtered.png')В результате получилось следующее изображение:

После применения стало гораздо проще различить объекты
Далее был реализован самописный медианный фильтр
def median_filter_diy(data, filter_size: int):
indexer = filter_size // 2
for x in range(data.size[0]):
for y in range(data.size[1]):
temp = []
for k in range(filter_size):
if x + k - indexer < 0 or x + k - indexer > data.size[0] - 1:
for c in range(filter_size):
temp.append((0, 0, 0))
else:
if y + k - indexer < 0 or y + indexer > data.size[1] - 1:
temp.append((0, 0, 0))
else:
for z in range(filter_size):
temp.append(data.getpixel((x + k - indexer, y + z - indexer)))
pixel = [0, 0, 0]
for i in range(3):
temp.sort(key=lambda x: x[i])
pixel[i] = temp[len(temp) // 2][i]
data.putpixel((x, y), tuple(pixel))
return dataОсобенность данной реализации - для каждого пиксела сортируется каждый канал по отдельности
После применения данного фильтра было получено следующее изображение
Далее был написан драйвер для замера скорости работы 2х вариантов
if __name__ == '__main__':
im = Image.open('./balloons_noisy.png')
sum_time_diy = 0
for i in range(100):
im2 = im.copy()
start = time.process_time()
median_filter_diy(im2, 3)
sum_time_diy += (time.process_time() - start)
sum_time_pil = 0
for i in range(100):
im2 = im.copy()
start = time.process_time()
im2.filter(ImageFilter.MedianFilter(3))
sum_time_pil += (time.process_time() - start)
print(f'{sum_time_diy=}, {sum_time_pil=}')Каждый вариант прогонялся по 100 раз на одном и том же изображении
В результате получились следующие замеры (в секундах):
- (самописная реализация) 146.73271800000006
- (реализация PIL) 5.470951000000184
Как видно код PIL работает в 30 раз быстрее чем наша реализация, скорее всего что во первых код PIL написан на C что сильно ускоряет процесс и в коде C используются векторные инструкции которые позволяют гораздо быстрее справлятся с матричными вычислениями
