|
|
|
|
|
""" |
|
|
Utility functions for image processing GUI. |
|
|
""" |
|
|
|
|
|
from PyQt5.QtGui import QPixmap |
|
|
from PyQt5.QtCore import Qt |
|
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas |
|
|
from matplotlib.figure import Figure |
|
|
from PIL import Image |
|
|
import numpy as np |
|
|
|
|
|
def qpixmap_from_path(p: str, max_size=(480, 360)) -> QPixmap: |
|
|
pix = QPixmap(p) |
|
|
if pix.isNull(): |
|
|
return QPixmap() |
|
|
w, h = max_size |
|
|
return pix.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation) |
|
|
|
|
|
def make_canvas(width=4, height=3, dpi=100): |
|
|
fig = Figure(figsize=(width, height), dpi=dpi) |
|
|
canvas = FigureCanvas(fig) |
|
|
ax = fig.add_subplot(111) |
|
|
fig.tight_layout() |
|
|
return canvas, ax |
|
|
|
|
|
def compute_gray_array(path): |
|
|
img = Image.open(path).convert('RGB') |
|
|
arr = np.array(img) |
|
|
gray = (0.299 * arr[:, :, 0] + 0.587 * arr[:, :, 1] + 0.114 * arr[:, :, 2]).astype(np.float32) |
|
|
return gray |
|
|
|
|
|
def compute_fft_magnitude(gray_arr, eps=1e-8): |
|
|
f = np.fft.fft2(gray_arr) |
|
|
fshift = np.fft.fftshift(f) |
|
|
mag = np.abs(fshift) |
|
|
mag_log = np.log1p(mag) |
|
|
return mag, mag_log |
|
|
|
|
|
def radial_profile(mag, center=None, nbins=100): |
|
|
h, w = mag.shape |
|
|
if center is None: |
|
|
center = (int(h / 2), int(w / 2)) |
|
|
y, x = np.indices((h, w)) |
|
|
r = np.sqrt((x - center[1]) ** 2 + (y - center[0]) ** 2) |
|
|
r_flat = r.ravel() |
|
|
mag_flat = mag.ravel() |
|
|
max_r = np.max(r_flat) |
|
|
if max_r <= 0: |
|
|
return np.linspace(0, 1, nbins), np.zeros(nbins) |
|
|
bins = np.linspace(0, max_r, nbins + 1) |
|
|
inds = np.digitize(r_flat, bins) - 1 |
|
|
radial_mean = np.zeros(nbins) |
|
|
for i in range(nbins): |
|
|
sel = inds == i |
|
|
if np.any(sel): |
|
|
radial_mean[i] = mag_flat[sel].mean() |
|
|
else: |
|
|
radial_mean[i] = 0.0 |
|
|
centers = 0.5 * (bins[:-1] + bins[1:]) / max_r |
|
|
return centers, radial_mean |