Spaces:
Build error
Build error
| 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: | |
| # 1. Convert to Grayscale | |
| img_gray = image.convert('L') | |
| # 2. Convert to Numpy Array | |
| img_array = np.array(img_gray) | |
| # 3. Compute FFT (Fast Fourier Transform) | |
| # f = np.fft.fft2(img_array) | |
| # fshift = np.fft.fftshift(f) | |
| # magnitude_spectrum = 20 * np.log(np.abs(fshift)) | |
| # Use a slightly more robust method for visualization | |
| f = np.fft.fft2(img_array) | |
| fshift = np.fft.fftshift(f) | |
| # Add epsilon to avoid log(0) | |
| magnitude_spectrum = 20 * np.log(np.abs(fshift) + 1e-9) | |
| # 4. Normalize to 0-255 for standard image display | |
| mag_min = magnitude_spectrum.min() | |
| mag_max = magnitude_spectrum.max() | |
| # Avoid division by zero if image is blank | |
| 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) | |
| # 5. Convert back to PIL Image | |
| spectrum_img = Image.fromarray(normalized) | |
| # 6. Encode to Base64 | |
| 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: | |
| # 1. Convert to Grayscale | |
| img_gray = image.convert('L') | |
| # 2. Apply Laplacian Filter (High-Pass) | |
| # This removes smooth areas and keeps edges/noise | |
| noise_map = img_gray.filter(ImageFilter.FIND_EDGES) | |
| # Note: FIND_EDGES is a simple approximation. For better grid visualization, | |
| # we can use a Kernel, but this is usually sufficient for "seeing" the grid. | |
| # 3. Invert to make lines black on white (easier to see) | |
| # noise_map = ImageOps.invert(noise_map) | |
| # Actually, white on black (default) effectively shows the "glowing" grid lines. | |
| # 4. Enhance Contrast/Brightness to make faint artifacts visible | |
| # We convert to numpy to scale | |
| arr = np.array(noise_map).astype(float) | |
| # Amplify | |
| arr = arr * 5.0 # Boost signal | |
| arr = np.clip(arr, 0, 255).astype(np.uint8) | |
| enhanced_map = Image.fromarray(arr) | |
| # 5. Encode | |
| 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 "" | |