| import numpy as np
|
| import numpy as np
|
| from PIL import Image, ImageFilter, ImageOps
|
| import io
|
| import base64
|
|
|
| class FrequencyAnalyzer:
|
| def __init__(self):
|
| pass
|
|
|
| def generate_spectrum(self, image: Image.Image) -> str:
|
| """
|
| Generates a 2D Frequency Spectrum (Magnitude Plot) from a PIL Image.
|
| Returns a base64 encoded PNG string of the spectrum.
|
| """
|
| try:
|
|
|
| img_gray = image.convert('L')
|
|
|
|
|
| img_array = np.array(img_gray)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| f = np.fft.fft2(img_array)
|
| fshift = np.fft.fftshift(f)
|
|
|
| magnitude_spectrum = 20 * np.log(np.abs(fshift) + 1e-9)
|
|
|
|
|
| mag_min = magnitude_spectrum.min()
|
| mag_max = magnitude_spectrum.max()
|
|
|
|
|
| if mag_max == mag_min:
|
| normalized = np.zeros_like(magnitude_spectrum, dtype=np.uint8)
|
| else:
|
| normalized = 255 * (magnitude_spectrum - mag_min) / (mag_max - mag_min)
|
| normalized = np.uint8(normalized)
|
|
|
|
|
| spectrum_img = Image.fromarray(normalized)
|
|
|
|
|
| buffered = io.BytesIO()
|
| spectrum_img.save(buffered, format="PNG")
|
| img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
|
|
|
| return img_str
|
|
|
| except Exception as e:
|
| print(f"Error generating frequency spectrum: {e}")
|
| return ""
|
|
|
| def generate_pattern_map(self, image: Image.Image) -> str:
|
| """
|
| Generates a Noise Pattern Map (High-Pass/Laplacian) to visualize
|
| checkerboard artifacts.
|
| """
|
| try:
|
|
|
| img_gray = image.convert('L')
|
|
|
|
|
|
|
| noise_map = img_gray.filter(ImageFilter.FIND_EDGES)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| arr = np.array(noise_map).astype(float)
|
|
|
|
|
| arr = arr * 5.0
|
| arr = np.clip(arr, 0, 255).astype(np.uint8)
|
|
|
| enhanced_map = Image.fromarray(arr)
|
|
|
|
|
| buffered = io.BytesIO()
|
| enhanced_map.save(buffered, format="PNG")
|
| img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
|
|
|
| return img_str
|
|
|
| except Exception as e:
|
| print(f"Error generating pattern map: {e}")
|
| return ""
|
|
|