Spaces:
Sleeping
Sleeping
File size: 6,147 Bytes
2ce4737 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
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()
|