Matika/ITDT/Gabor.py

100 lines
3 KiB
Python
Raw Normal View History

2025-03-09 11:33:42 +01:00
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()