Часть 2:
В данной части выполняется изменённая реализация первой части. А именно на основе исходной маски создаются две другие — с небольшим отклонением и выраженным. Код реализации представлен в Листинге 4. Для восстановления использовался метод Винера.
В результате можно наблюдать довольно качественное восстановленное изображение при использовании маски с небольшим отклонением (Рисунок 6). Тогда как при значительном на выходе получается мозаичная картинка — множество артефактов (Рисунок 7).
Листинг 4 — Вариант с модифицируемыми масками (метод Винера)
import cv2
from skimage import restoration
import numpy as np
# Сферическая маска расфокусировки
def spherical_blur_mask(r):
grid_size = 2 * r + 1 # Диаметр маски
y_coords, x_coords = np.ogrid[-r:r + 1, -r:r + 1] # Координатная сетка
is_inside_circle = (x_coords ** 2 + y_coords ** 2) <= (r ** 2)
mask = np.zeros((grid_size, grid_size), dtype=np.float32)
mask[is_inside_circle] = 1.0
mask = mask / np.sum(mask) # Нормировка
return mask
# Функция для создания измененной сферической маски
def generate_modified_mask(original_radius, variation_factor):
new_radius = int(original_radius * variation_factor)
new_radius = max(1, new_radius) # радиус должен быть >=1
return spherical_blur_mask(new_radius)
# Загрузка изображения
input_imag = cv2.imread('img/p2.jpg')
input_image = input_imag.astype(np.float32) / 255.0 # Нормализация
# Основной радиус сферического размытия
base_radius = 5
PSF_blur = spherical_blur_mask(base_radius)
print(PSF_blur)
# Применение размытия
blur_image = cv2.filter2D(input_image, -1, PSF_blur)
# Создание модифицированных масок
PSF_blur_slightly_modified = generate_modified_mask(base_radius, 1.1) # отклонение 10 %
PSF_blur_significantly_modified = generate_modified_mask(base_radius, 2) # в 2 раза
# Параметр шума
noise_var = 0.01
# Восстановление с незначительным и существенным отклонением
restored_low = input_image.copy()
restored_hight = input_image.copy()
for c in range(3): # По каналам
restored_low[:, :, c] = restoration.wiener(
blur_image[:, :, c], PSF_blur_slightly_modified, noise_var)
restored_hight[:, :, c] = restoration.wiener(
blur_image[:, :, c], PSF_blur_significantly_modified, noise_var)
# Ограничение и денормализация
restored_low = np.clip(restored_low, 0., 1.)
restored_hight = np.clip(restored_hight, 0., 1.)
restored_low = (restored_low * 255.).astype(np.uint8)
restored_hight = (restored_hight * 255.).astype(np.uint8)
path = 'img/p2'
cv2.imwrite(path+'restored_low.jpg', restored_low)
cv2.imwrite(path+'restored_hight.jpg', restored_hight)
Рисунок 6 — Восстановленное изображение (маска с отклонением 10 %)
Рисунок 7 — Восстановленное изображение (Маска с отклонением в 2 раза)
Далее реализация с изменёнными масками была повторена, ноу же с использованием в качестве способа восстановления метода Ричардсона-Люси, и выбранным на основе предыдущих опытов количеством итераций — 16. Код реализации приведен в Листинге 5. Результаты работы программы представлены на Рисунках 8-9.
Как можно видеть, при небольшом отклонении маски получается достаточно хорошее изображение (Рисунок 8). С использованием метода Ричардсона-Люси (16 итераций) в отличие от метода Винера нет таких сильных артефактов по краям, в то же время центральная часть менее чёткая.
При выраженном отклонении заметно сильное смазывание, необычное выделение контуров на контрастных участках, как будто подсвечивание (Рисунок 9).
Листинг 5 — Вариант с модифицируемыми масками (метод Ричардсона-Люси)
import cv2
from skimage import restoration
import numpy as np
# Сферическая маска расфокусировки
def spherical_blur_mask(r):
grid_size = 2 * r + 1
y_coords, x_coords = np.ogrid[-r:r + 1, -r:r + 1]
is_inside_circle = (x_coords ** 2 + y_coords ** 2) <= (r ** 2)
mask = np.zeros((grid_size, grid_size), dtype=np.float32)
mask[is_inside_circle] = 1.0
return mask / np.sum(mask)
# Генерация модифицированной маски
def generate_modified_mask(original_radius, variation_factor):
new_radius = max(1, int(original_radius * variation_factor))
return spherical_blur_mask(new_radius)
# Метод Ричардсона-Люси
def richardson_lucy_deblur(blurred_image, psf, num_iter=16):
blurred_float = blurred_image.astype(np.float32) / 255.0
deblurred = np.zeros_like(blurred_float)
for c in range(3):
deblurred[..., c] = restoration.richardson_lucy(
blurred_float[..., c], psf, num_iter=num_iter)
return np.clip(deblurred * 255, 0, 255).astype(np.uint8)
# Загрузка изображения
input_imag = cv2.imread('img/p2.jpg')
input_image = input_imag.astype(np.float32) / 255.0
# Базовая маска расфокусировки
base_radius = 5
PSF_blur = spherical_blur_mask(base_radius)
# Применяем размытие
blur_image = cv2.filter2D(input_image, -1, PSF_blur)
# Модифицированные маски
psf_low = generate_modified_mask(base_radius, 1.1)
psf_high = generate_modified_mask(base_radius, 2)
# Восстановление методом Ричардсона–Люси
blur_image_uint8 = (blur_image * 255.).astype(np.uint8)
restored_low = richardson_lucy_deblur(blur_image_uint8, psf_low)
restored_hight = richardson_lucy_deblur(blur_image_uint8, psf_high)
path = 'img/p2'
cv2.imwrite(path+'rl_restored_low.jpg', restored_low)
cv2.imwrite(path+'rl_restored_high.jpg', restored_hight)
Рисунок 8 — Восстановленное изображение, отклонение маски 10%, метод Ричардсона-Люси
Рисунок 9 — Восстановленное изображение, отклонение маски 2 раза, метод Ричардсона-Люси
