
7
.pdf
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
Кафедра 41
ПРЕПОДАВАТЕЛЬ |
|
|
|
|
|
|
доц., к.т.н., доц. |
|
|
|
О. О. Жаринов |
|
|
|
|
|
|
|
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
Лабораторная работа №7
Основы цифровой фильтрации изображений. Пространственные фильтры
по курсу: Мультимедиа технологии
СТУДЕНТКА ГР. № Z0411 |
07.04.25 |
|
М. В. Карелина |
||
|
|
|
|
|
|
|
номер группы |
|
подпись, дата |
|
инициалы, фамилия |
Номер студенческого билета: 2020/3477
Санкт-Петербург
2025
Цель работы:
Изучить основы обработки изображений на примере методов фильтрации с использованием пространственных фильтров.
Вариант 7.
Вариант №2 с неравномерным смазом: столбец в центре маски представляет собой последовательность линейно возрастающих значений.
В данной работе рассматриваются методы восстановления изображений, искажённых смазыванием (размытиями), с использованием двух известных алгоритмов: фильтра Винера и метода Люси-Ричардсон. Целью является оценка эффективности восстановления изображений в различных условиях, включая:
-точное знание маски смазывания (PSF);
-ошибки в модели PSF (неправильная маска);
-применение на реальных изображениях с неизвестными искажениями.
Фильтр Винера представляет собой линейный метод восстановления, который минимизирует среднеквадратичную ошибку между восстановленным и оригинальным изображениями. Этот метод предполагает знание или оценку мощности шума и спектра изображения.
Метод Люси-Ричардсон — это итеративный алгоритм, основанный на вероятностной модели (по Байесу), который особенно эффективен при наличии размытости и шума, но требует знания PSF и определения числа итераций.
Для начала рассмотрим код представленный в листинге 1, выполняющий обработку изображения с использованием цветовой модели LAB для улучшения его яркости. Сначала изображение загружается и преобразуется из модели BGR в LAB. Затем извлекается и нормируется канал яркости. Далее создаётся маска пространственного фильтра (PSF), которая

применяется к матрице яркости для фильтрации. После этого обрабатываются значения яркости, чтобы избежать отрицательных значений, и изменённые данные возвращаются в LAB-изображение. Затем LAB-изображение преобразуется обратно в модель BGR. На рисунке 1 представлено оригинальное изображение которое в дальнейшем подверглось размытию через приложение-редактор. На рисунках 2 и 3 результат выполнения программы.
Листинг 1. Программа, реализующая один из вариантов универсального метода
повышения резкости расфокусированного изображения
import cv2
import numpy as np
import matplotlib.pyplot as plt
#Чтение исходного изображения input_image = cv2.imread('LR7.jpg')
#Преобразование изображения из цветовой модели BGR в LAB
LAB_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2LAB)
#Извлечение матрицы яркости (канал L) из LAB-изображения и нормировка значений
L = LAB_image[:, :, 0] / 100 # Значения канала L находятся в диапазоне от 0
до 100
#Задаем маску (PSF - функцию пространственного фильтра) для фильтрации
c = 0.60 # Параметр, который можно настраивать для изменения фильтрующего эффекта
PSF = np.array([
[-c, -c, -c], # Соседние пиксели в горизонтальном и вертикальном направлениях
[-c, 1 + 8 * c, -c], # Центральный пиксель с весом, увеличенным на 8*c [-c, -c, -c] # Соседние пиксели в горизонтальном и вертикальном
направлениях
])
#Применяем фильтрацию к матрице яркости L с использованием заданной маски
PSF
L_out = cv2.filter2D(L, -1, PSF)
#Обработка яркости, чтобы избежать отрицательных значений
L_max = np.max(L_out) # Находим максимальное значение яркости после фильтрации
L_out = np.clip(L_out, a_min=0., a_max=L_max) # Обрезаем значения, чтобы избежать искажений
# Заменяем изменённую матрицу яркости обратно в LAB-изображение LAB_image[:, :, 0] = L_out * 100 # Умножаем на 100, чтобы вернуть значения в диапазон от 0 до 100
#Преобразование LAB-изображения обратно в цветовую модель BGR image_out = cv2.cvtColor(LAB_image, cv2.COLOR_LAB2BGR)
#Визуализация исходного и обработанного изображений

plt.figure(figsize=(10, 5)) |
|
|
# Отображение исходного изображения |
|
|
plt.subplot(1, 2, 1) |
|
|
plt.imshow(cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)) |
# Преобразуем BGR |
|
в RGB для корректного отображения |
|
|
plt.title('Исходное изображение') |
|
|
plt.axis('off') |
# Убираем оси |
|
# Отображение обработанного изображения |
|
|
plt.subplot(1, 2, 2) |
|
|
plt.imshow(cv2.cvtColor(image_out, cv2.COLOR_BGR2RGB)) |
# Преобразуем BGR в |
|
RGB для корректного отображения |
|
|
plt.title('Обработанное изображение') |
|
|
plt.axis('off') |
# Убираем оси |
|
plt.tight_layout() # Убираем лишние пробелы между подграфиками plt.show() # Показываем график
# Сохранение обработанного изображения cv2.imwrite('LR7.1.jpg', image_out)
Рисунок 1 - Оригинальное изображение

Рисунок 2 - Результат обработки универсальным методом повышения резкости
Теперь перейдём к обработке изображения с использованием методов Люси-Ричардсона и Винера. (Листинг 2)
Сначала мы загрузим оригинальное изображение. Затем создадим правильную маску, которая будет использоваться для искажения изображения, задав искажающую маску в виде матрицы. Для этого применим функцию blur_mask с заданными параметрами, например, размером 9 и углом
35 градусов. После чего нанесём размытие на изображение, используя функцию свёртки cv2.filter2D, применив к нему созданную маску. Результат обработке на рисунке 3.
Листинг 2. Реализация методов восстановления изображения с помощью фильтра
Винера и Люси-Ричардсона
import cv2
from skimage import restoration import numpy as np
import matplotlib.pyplot as plt
#Функция, создающая смаз:
#size - размер размаза в пикселях,
#angle - направление смаза, в градусах def blur_mask(size, angle):
k = np.zeros((size, size), dtype=np.float32)
k[(size - 1) // 2, :] = np.ones(size, dtype=np.float32)
k = cv2.warpAffine(k, cv2.getRotationMatrix2D((size / 2 - 0.5, size / 2 - 0.5), angle, 1.0), (size, size))
k = k / np.sum(k) # нормировка return k

# Загрузка входного изображения input_image = cv2.imread('LR7org.jpg')
#Нормировка данных изображения и перевод во float: input_image = input_image.astype(np.float32) / 255.
#Задаем искажающую маску в виде матрицы:
PSF_blur = blur_mask(size=9, angle=35)
# Размазываем изображение:
blur_image = cv2.filter2D(input_image, -1, PSF_blur)
#Восстановление изображения методом Винера noise_var = 0.01 # подбор уровня шума image_deblur_wiener = input_image.copy()
#Обработка по трем цветовым каналам раздельно for i in range(3):
image_deblur_wiener[:, :, i] = restoration.wiener(blur_image[:, :, i], PSF_blur, noise_var)
#Ограничение и денормировка
image_deblur_wiener = np.clip(image_deblur_wiener, 0., 1.) image_deblur_wiener = (image_deblur_wiener * 255.).astype(np.uint8)
# Восстановление изображения методом Люси-Ричардсона its = 6 # количество итераций
image_deblur_rl = input_image.copy()
for i in range(3):
image_deblur_rl[:, :, i] = restoration.richardson_lucy(blur_image[:, :, i], PSF_blur, num_iter=its)
# Ограничение и денормировка
image_deblur_rl = np.clip(image_deblur_rl, 0., 1.) image_deblur_rl = (image_deblur_rl * 255.).astype(np.uint8)
# Сохранение изображений cv2.imwrite('LR7.2.jpg', image_deblur_wiener) cv2.imwrite('LR7.3.jpg', image_deblur_rl)
# Визуализация оригинального, смазанного и восстановленных изображений plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1) plt.imshow(cv2.cvtColor(blur_image, cv2.COLOR_BGR2RGB)) plt.title('Смазанное изображение')
plt.axis('off')
plt.subplot(1, 3, 2) plt.imshow(cv2.cvtColor(image_deblur_wiener, cv2.COLOR_BGR2RGB)) plt.title('Восстановленное изображение (Винер)')
plt.axis('off')
plt.subplot(1, 3, 3) plt.imshow(cv2.cvtColor(image_deblur_rl, cv2.COLOR_BGR2RGB)) plt.title('Восстановленное изображение (Люси-Ричардсон)') plt.axis('off')
plt.tight_layout() plt.show()

Рисунок 3 - Результат обработки методами восстановления изображения с помощью фильтра Винера и Люси-Ричардсона
Теперь перейдём к процессу восстановления изображений, где будем использовать функции, принимающие маски искажений, не соответствующие той, которая была изначально использована для внесения искажений. Сначала загрузим оригинальное изображение и создадим искажающую маску с определёнными параметрами. Затем мы будем обрабатывать изображение,
передавая в функции восстановления маски, которые отличаются от используемой для смазывания. Это позволит оценить устойчивость методов восстановления, таких как Люси-Ричардсон и Винер, к ошибкам в модели пространственного фильтра (PSF). Программный код показан в листинге 3.
Листинг 3. Реализация методов восстановления изображения с помощью фильтра
Винера и Люси-Ричардсона с неправильной маской смазывания
import cv2
from skimage import restoration import numpy as np
import matplotlib.pyplot as plt
#Функция, создающая смаз: def blur_mask(size, angle):
k = np.zeros((size, size), dtype=np.float32)
k[(size - 1) // 2, :] = np.ones(size, dtype=np.float32)
k = cv2.warpAffine(k, cv2.getRotationMatrix2D((size / 2 - 0.5, size / 2 - 0.5), angle, 1.0), (size, size))
k = k / np.sum(k) # нормировка return k
#Загрузка входного изображения
input_image = cv2.imread('LR7org.jpg')
#Нормировка данных изображения и перевод во float: input_image = input_image.astype(np.float32) / 255.
#Задаем корректную искажающую маску в виде матрицы: PSF_blur = blur_mask(size=9, angle=35)
#Размазываем изображение:

blur_image = cv2.filter2D(input_image, -1, PSF_blur)
# Создание неправильной маски
incorrect_PSF = blur_mask(size=15, angle=15)
#Восстановление изображения методом Винера с неправильной маской noise_var = 0.01 # подбор уровня шума
image_deblur_wiener = input_image.copy()
#Обработка по трем цветовым каналам раздельно
for i in range(3):
image_deblur_wiener[:, :, i] = restoration.wiener(blur_image[:, :, i], incorrect_PSF, noise_var)
# Ограничение и денормировка
image_deblur_wiener = np.clip(image_deblur_wiener, 0., 1.) image_deblur_wiener = (image_deblur_wiener * 255.).astype(np.uint8)
# Восстановление изображения методом Люси-Ричардсона с неправильной маской its = 6 # количество итераций
image_deblur_rl = input_image.copy()
for i in range(3):
image_deblur_rl[:, :, i] = restoration.richardson_lucy(blur_image[:, :, i], incorrect_PSF, num_iter=its)
# Ограничение и денормировка
image_deblur_rl = np.clip(image_deblur_rl, 0., 1.) image_deblur_rl = (image_deblur_rl * 255.).astype(np.uint8)
# Сохранение изображений cv2.imwrite('LR7.4.jpg', image_deblur_wiener) cv2.imwrite('LR7.5.jpg', image_deblur_rl)
# Визуализация оригинального, смазанного и восстановленных изображений plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1) plt.imshow(cv2.cvtColor(blur_image, cv2.COLOR_BGR2RGB)) plt.title('Смазанное изображение', fontsize=9) plt.axis('off')
plt.subplot(1, 3, 2) plt.imshow(cv2.cvtColor(image_deblur_wiener, cv2.COLOR_BGR2RGB))
plt.title('Восстановленное изображение (Винер, неправильная маска)', fontsize=9)
plt.axis('off')
plt.subplot(1, 3, 3) plt.imshow(cv2.cvtColor(image_deblur_rl, cv2.COLOR_BGR2RGB))
plt.title('Восстановленное изображение (Люси-Ричардсон, неправильная маска)', fontsize=9)
plt.axis('off')
plt.tight_layout() plt.show()
Для тестирования восстановления изображений с использованием фильтров Винера и Люси-Ричардсона была выбрана неправильная маска с параметрами 15х15. Маска с размером 15x15 пикселей создаёт широкое размазывание, что приводит к заметной потере деталей изображения. Угол в

15 градусов обеспечивает наклонное размазывание, которое может негативно сказаться на вертикальных и горизонтальных линиях. Такие условия позволяют проверить устойчивость алгоритмов восстановления к сложным искажениям, выявляя их слабые места и возможности для улучшения.
Результат выполнения на рисунке 4.
Рисунок 4 - Результат обработки методами восстановления изображения с помощью фильтра Винера и Люси-Ричардсона
Далее было решено изменить маску на 10x10, что позволило нам оценить влияние меньшего размытия на процесс восстановления изображений. Использование этой маски обеспечило сохранение большего количества деталей и сделало восстановление более эффективным. Угол в 10
градусов продолжал создавать наклонное размазывание, однако благодаря меньшему размеру маски изображение стало менее искажённым, что положительно сказалось на результатах работы алгоритмов. Результат выполнения на рисунке 5.
Рисунок 5 - Результат обработки методами восстановления изображения с помощью фильтра Винера и Люси-Ричардсона

Далее мы переходим к выполнению задания по варианту, в котором используется неравномерное размазывание. В этом случае столбец в центре маски будет представлять собой последовательность линейно возрастающих значений, что создаст более сложные условия для тестирования восстановительных алгоритмов. Мы возьмём уже имеющийся код с правильной маской и адаптируем его под новые параметры. Программой код в листинге 3. Результат представлен на рисунке 6.
Листинг 3. Реализация задания по варианту
import cv2
from skimage import restoration import numpy as np
import matplotlib.pyplot as plt
#Функция, создающая равномерный смаз def blur_mask(size, angle):
k = np.zeros((size, size), dtype=np.float32)
k[(size - 1) // 2, :] = np.ones(size, dtype=np.float32)
k = cv2.warpAffine(k, cv2.getRotationMatrix2D((size / 2 - 0.5, size / 2 - 0.5), angle, 1.0), (size, size))
k = k / np.sum(k) # Нормировка return k
#Функция, создающая маску с линейно возрастающими значениями в центральном столбце
def create_linear_blur_mask(size):
PSF = np.zeros((size, size), dtype=np.float32) center_index = size // 2
for i in range(size):
PSF[i, center_index] = i / (size - 1) # Линейное увеличение от 0 до
1
PSF /= np.sum(PSF) # Нормировка return PSF
# Загрузка входного изображения input_image = cv2.imread('LR7org.jpg')
input_image = input_image.astype(np.float32) / 255. # Нормировка данных изображения
#Создаем равномерную маску для размазывания
PSF_blur = blur_mask(size=9, angle=0)
blur_image = cv2.filter2D(input_image, -1, PSF_blur) # Размазываем изображение
#Создание маски с линейно возрастающими значениями
linear_PSF = create_linear_blur_mask(size=15) # Здесь создается маска для восстановления
#Восстановление изображения методом Винера noise_var = 0.01 # Уровень шума image_deblur_wiener = input_image.copy()
#Обработка по трем цветовым каналам раздельно for i in range(3):
image_deblur_wiener[:, :, i] = restoration.wiener(blur_image[:, :, i], linear_PSF, noise_var)