Matika/ITDT/Gabor.py
2025-03-09 11:33:42 +01:00

99 lines
3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage as ndi
from skimage.io import imread
from skimage.util import img_as_float
from skimage.filters import gabor_kernel
def compute_feats(image, kernels):
feats = np.zeros((len(kernels), 2), dtype=np.double)
for k, kernel in enumerate(kernels):
filtered = ndi.convolve(image, kernel, mode='wrap')
feats[k, 0] = filtered.mean()
feats[k, 1] = filtered.var()
return feats
def match(feats, ref_feats):
min_error = np.inf
min_i = None
for i in range(ref_feats.shape[0]):
error = np.sum((feats - ref_feats[i, :])**2)
if error < min_error:
min_error = error
min_i = i
return min_i
sigma = 10 # 1 - 10
frequency = 0.35 # 0.05 - 0.35
kernels = []
for theta in range(4):
theta = theta / 4. * np.pi
kernel = np.real(gabor_kernel(frequency, theta=theta, n_stds=sigma))
kernels.append(kernel)
shrink = (slice(0, None, 3), slice(0, None, 3))
disc = img_as_float(imread("discord-logo.png", as_gray=True))[shrink]
feng = img_as_float(imread("Feng_wind.jpg", as_gray=True))[shrink]
vazka = img_as_float(imread("vazka.png", as_gray=True))[shrink]
image_names = ('Discord', 'Znak', 'Vážka')
images = (disc, feng, vazka)
# prepare reference features
ref_feats = np.zeros((3, len(kernels), 2), dtype=np.double)
ref_feats[0, :, :] = compute_feats(disc, kernels)
ref_feats[1, :, :] = compute_feats(feng, kernels)
ref_feats[2, :, :] = compute_feats(vazka, kernels)
def power(image, kernel):
# Normalize images for better comparison.
image = (image - image.mean()) / image.std()
return np.sqrt(ndi.convolve(image, np.real(kernel), mode='wrap')**2 +
ndi.convolve(image, np.imag(kernel), mode='wrap')**2)
# Plot a selection of the filter bank kernels and their responses.
results = []
kernel_params = []
for theta in range(0, 10):
theta = theta / np.pi
kernel = gabor_kernel(frequency, theta=theta)
params = f"Θ={18*(theta*np.pi):.0f}°"
kernel_params.append(params)
# Save kernel and the power image for each image
results.append((kernel, [power(img, kernel) for img in images]))
fig, axes = plt.subplots(nrows=len(results)+1, ncols=len(image_names)+1, figsize=(4, 9))
plt.gray()
fig.suptitle(f'Gaborovy filtry\n pro λ={frequency}, ϕ={0}, σ={sigma} a γ={1}.', fontsize=12)
axes[0][0].axis('off')
# Plot original images
for label, img, ax in zip(image_names, images, axes[0][1:]):
ax.imshow(img)
ax.set_title(label, fontsize=9)
ax.axis('off')
for label, (kernel, powers), ax_row in zip(kernel_params, results, axes[1:]):
# Plot Gabor kernel
ax = ax_row[0]
ax.imshow(np.real(kernel))
ax.set_ylabel(label, fontsize=7)
ax.set_xticks([])
ax.set_yticks([])
# Plot Gabor responses with the contrast normalized for each filter
vmin = np.min(powers)
vmax = np.max(powers)
for patch, ax in zip(powers, ax_row[1:]):
ax.imshow(patch, vmin=vmin, vmax=vmax)
ax.axis('off')
plt.show()