Image_FFT_Visualizer / localRun_NoStramlit.py
Mattral's picture
Create localRun_NoStramlit.py
2ce4737 verified
import numpy as np
import cv2
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import os
import csv
# 1. Function to apply Fast Fourier Transform to a colored image (separate for each channel)
def apply_fft(image):
"""Apply Fast Fourier Transform to a colored image (separate for each channel)"""
fft_channels = []
for channel in cv2.split(image): # Split the image into its color channels (B, G, R)
fft = np.fft.fft2(channel)
fft_shifted = np.fft.fftshift(fft) # Shift the zero frequency to the center
fft_channels.append(fft_shifted)
return fft_channels
# 2. Function to display frequency components of each color channel in interactive 3D plots using Matplotlib
def show_frequency_components_3d(fft_channels, title='Frequency Components'):
"""Display the magnitude and phase of the FFT for each channel (R, G, B) in 3D with Matplotlib"""
channel_names = ['Blue Channel', 'Green Channel', 'Red Channel']
# Create a figure for 3D plotting
fig = plt.figure(figsize=(18, 6))
# Loop through each channel's FFT data
for i, fft_data in enumerate(fft_channels):
magnitude = np.abs(fft_data) # Magnitude spectrum
phase = np.angle(fft_data) # Phase spectrum
# Generate grid for the 3D plot (x, y grid of frequencies)
rows, cols = magnitude.shape
x = np.linspace(-cols // 2, cols // 2, cols)
y = np.linspace(-rows // 2, rows // 2, rows)
X, Y = np.meshgrid(x, y)
# Create a subplot for each channel's magnitude and phase
ax = fig.add_subplot(1, 6, 2 * i + 1, projection='3d')
ax.set_title(f'{channel_names[i]} - Magnitude')
ax.plot_surface(X, Y, magnitude, cmap='viridis', edgecolor='none')
ax = fig.add_subplot(1, 6, 2 * i + 2, projection='3d')
ax.set_title(f'{channel_names[i]} - Phase')
ax.plot_surface(X, Y, phase, cmap='inferno', edgecolor='none')
plt.suptitle(title, fontsize=16)
plt.tight_layout()
plt.show()
# 3. Function to apply percentage-based filtering to the FFT (for each channel)
def filter_fft_percentage(fft_channels, percentage):
"""Apply percentage-based filtering, keeping the highest-magnitude frequency components"""
filtered_fft = []
for fft_data in fft_channels:
magnitude = np.abs(fft_data)
flat_mag = magnitude.flatten()
sorted_mag = np.sort(flat_mag)[::-1] # Sort magnitudes in descending order
# Determine the threshold for the given percentage
num_elements_to_keep = int(len(sorted_mag) * percentage / 100)
threshold = sorted_mag[num_elements_to_keep - 1] if num_elements_to_keep > 0 else 0
# Create a mask to keep only the top frequencies
mask = magnitude >= threshold
filtered_fft.append(fft_data * mask) # Apply mask to the FFT data
return filtered_fft
# 4. Function to apply inverse Fourier transform to reconstruct the color image
def inverse_fft(filtered_fft):
"""Apply inverse Fourier transform to reconstruct the image from filtered FFT"""
reconstructed_channels = []
for fft_data in filtered_fft:
fft_ishift = np.fft.ifftshift(fft_data) # Reverse FFT shift
img_reconstructed = np.fft.ifft2(fft_ishift) # Apply inverse FFT
img_reconstructed = np.abs(img_reconstructed) # Get the magnitude of the result
# Normalize and convert to uint8 for image format
img_normalized = cv2.normalize(img_reconstructed, None, 0, 255, cv2.NORM_MINMAX)
reconstructed_channels.append(img_normalized.astype(np.uint8))
# Merge the channels back into a color image (BGR format)
return cv2.merge(reconstructed_channels)
# 5. Main function to process images in batches
def process_images():
"""Main function to process images, apply FFT, and filter results"""
# Create directories if they don't exist
os.makedirs('Modified', exist_ok=True)
# Ask user for the percentage of top frequencies to keep
percentage = float(input("Enter the percentage of highest-magnitude frequencies to keep (0-100): "))
print(f"Applying percentage-based filtering: Keeping top {percentage}% of frequencies.")
# Create CSV logging file
with open('fft_features.csv', 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(['Image', 'Max Magnitude', 'Mean Magnitude', 'Non-zero Count'])
# Process each image in the 'original' folder
image_filenames = [filename for filename in os.listdir('original')
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff'))]
# Process all images
for i, filename in enumerate(image_filenames):
# Read image (colored)
img_path = os.path.join('original', filename)
img = cv2.imread(img_path)
# Apply FFT to each channel (RGB)
fft_channels = apply_fft(img)
# Apply percentage-based filtering
filtered_fft = filter_fft_percentage(fft_channels, percentage)
# Reconstruct the image using inverse FFT
reconstructed = inverse_fft(filtered_fft)
# Show frequency components (filtered FFT) as interactive 3D plots using Matplotlib
show_frequency_components_3d(filtered_fft, f'Filtered FFT - {filename}')
# Log FFT features for the first channel (R)
magnitude = np.abs(filtered_fft[0]) # Just checking the first channel's magnitude
non_zero = magnitude > 0
csv_writer.writerow([
filename,
np.max(magnitude),
np.mean(magnitude[non_zero]) if np.any(non_zero) else 0,
np.count_nonzero(non_zero)
])
# Save reconstructed image
cv2.imwrite(os.path.join('Modified', filename), reconstructed)
print("Processing completed successfully!")
# Run the main function
if __name__ == "__main__":
process_images()