GPU-accelerated image processing using CUDA and cuFFT for frequency domain filtering and restoration.
** Still in development **
- Low-Pass Filters: Noise reduction and smoothing
- High-Pass Filters: Edge enhancement and sharpening
- Band-Pass Filters: Specific frequency range isolation
- Band-Reject Filters: Notch filtering for specific frequency removal
Each filter mode supports three implementation types:
- Ideal: Sharp cutoff (may cause ringing artifacts)
- Gaussian: Smooth transition (best for most cases)
- Butterworth: Configurable sharpness (adjustable order)
- Unsharp Masking: Advanced edge enhancement
- Noise Reduction: Remove high-frequency noise
- Edge Detection: Extract edge information
- Frequency Band Enhancement: Target specific patterns
src/
├── cuda_utils.cuh # CUDA error checking, DeviceBuffer wrapper
├── image_gpu.cuh # Image loading/saving with stb_image
├── image_conversion.cuh # Image <-> Complex conversions, FFT utilities
├── frequency_filters.cuh # All frequency domain filter kernels
├── image_restoration.cuh # High-level restoration API
├── fft.cuh # FFT wrapper functions
├── scale.cuh # FFT scaling utilities
└── ...
#include "src/image_restoration.cuh"
int main() {
// Load input image
Image input("input.png");
Image output(input.width, input.height, 1);
// Configure filter parameters
FilterParams params;
params.type = FilterType::GAUSSIAN;
params.cutoff_freq = 50.0f;
// Apply low-pass filter for noise reduction
ImageRestoration::restoreImage(input, output,
RestorationMode::LOW_PASS, params);
// Save result
stbi_write_png("output.png", output.width, output.height, 1,
output.image_data, output.width);
return 0;
}FilterParams params;
params.unsharp_amount = 1.5f; // Enhancement strength
params.unsharp_radius = 30.0f; // Blur radius
ImageRestoration::unsharpMask(input, output, params);// Ideal filter (sharp cutoff)
params.type = FilterType::IDEAL;
params.cutoff_freq = 50.0f;
// Butterworth filter (customizable)
params.type = FilterType::BUTTERWORTH;
params.cutoff_freq = 50.0f;
params.butterworth_order = 2; // Higher = sharper transition
// Gaussian filter (smooth)
params.type = FilterType::GAUSSIAN;
params.cutoff_freq = 50.0f;FilterParams params;
params.type = FilterType::GAUSSIAN;
params.low_freq = 20.0f;
params.high_freq = 60.0f;
params.center_freq = 40.0f;
params.bandwidth = 20.0f;
ImageRestoration::restoreImage(input, output,
RestorationMode::BAND_PASS, params);LOW_PASS- Smooth/blur, remove high frequenciesHIGH_PASS- Sharpen, remove low frequenciesBAND_PASS- Keep only specific frequency rangeBAND_REJECT- Remove specific frequency rangeUNSHARP_MASK- Advanced sharpening technique
IDEAL- Sharp cutoff (ideal filter)GAUSSIAN- Smooth Gaussian rolloffBUTTERWORTH- Configurable transition steepness
struct FilterParams {
FilterType type; // Filter implementation type
float cutoff_freq; // Cutoff frequency (low/high-pass)
float low_freq; // Band-pass lower bound
float high_freq; // Band-pass upper bound
float center_freq; // Band-pass center
float bandwidth; // Band-pass width
int butterworth_order; // Butterworth filter order
float unsharp_amount; // Unsharp mask strength
float unsharp_radius; // Unsharp mask blur radius
};// Full restoration pipeline
static void restoreImage(const Image& input, Image& output,
RestorationMode mode, const FilterParams& params);
// Specialized unsharp masking
static void unsharpMask(const Image& input, Image& output,
const FilterParams& params);
// Apply filter to frequency domain data (advanced)
static void applyFilter(cufftComplex* d_freq_data, int width, int height,
RestorationMode mode, const FilterParams& params);For advanced users who want direct access to kernels:
// Convert image to complex for FFT
__global__ void imageToComplex(unsigned char* img_data,
cufftComplex* complex_data,
int width, int height, int channels);
// Convert complex back to image
__global__ void complexToImage(cufftComplex* complex_data,
unsigned char* image_data,
int width, int height);
// Center frequency spectrum
__global__ void fftShift(cufftComplex* data, cufftComplex* output,
int width, int height);// Low-pass filters
__global__ void idealLowPassFilter(cufftComplex* freq_data, ...);
__global__ void gaussianLowPassFilter(cufftComplex* freq_data, ...);
__global__ void butterworthLowPassFilter(cufftComplex* freq_data, ...);
// High-pass filters
__global__ void idealHighPassFilter(cufftComplex* freq_data, ...);
__global__ void gaussianHighPassFilter(cufftComplex* freq_data, ...);
__global__ void butterworthHighPassFilter(cufftComplex* freq_data, ...);
// Band-pass filters
__global__ void idealBandPassFilter(cufftComplex* freq_data, ...);
__global__ void gaussianBandPassFilter(cufftComplex* freq_data, ...);
__global__ void butterworthBandPassFilter(cufftComplex* freq_data, ...);
// Band-reject filter
__global__ void bandRejectFilter(cufftComplex* freq_data, ...);- CUDA Toolkit (11.0+)
- CMake (3.18+)
- C++ compiler with C++14 support
mkdir build
cd build
cmake ..
cmake --build . --config Release# Run the demonstration program
./sharpening images/input.png
# Output will be in images/restored/The sharpening.cu demonstration program generates:
Noise Reduction (Low-Pass):
lowpass_gaussian.png- Smooth noise reductionlowpass_butterworth.png- Controlled transitionlowpass_ideal.png- Sharp cutoff
Edge Enhancement (High-Pass):
highpass_gaussian.png- Smooth edge enhancementhighpass_butterworth.png- Adjustable sharpnesshighpass_ideal.png- Maximum sharpness
Band-Pass Filtering:
bandpass_gaussian.png- Specific frequency rangebandpass_butterworth.png- Controlled band selectionbandpass_ideal.png- Sharp band isolation
Unsharp Masking:
unsharp_light.png- Subtle enhancement (1.2x)unsharp_medium.png- Moderate enhancement (1.5x)unsharp_strong.png- Strong enhancement (2.0x)
- Use Gaussian filters for general purposes (smooth, no ringing)
- Adjust cutoff frequencies based on image size (larger images need higher values)
- Butterworth order: 2-4 is usually optimal
- Unsharp masking: Start with amount=1.5, radius=30 and adjust
- Memory: All operations use GPU memory for maximum performance
Images are transformed to frequency domain using 2D FFT, where:
- Low frequencies = smooth regions, overall structure
- High frequencies = edges, fine details, noise
Filtering in frequency domain is multiplication, which corresponds to convolution in spatial domain.
- Ideal: H(u,v) = 1 inside cutoff, 0 outside (sharp but ringing)
- Gaussian: H(u,v) = exp(-D²/2σ²) (smooth, no ringing)
- Butterworth: H(u,v) = 1/(1+(D/D₀)^2n) (adjustable smoothness)
Where D is distance from frequency center.
You can do whatever you want LICENSE
- Rafael C. Gonzalez & Richard E. Woods, "Digital Image Processing"
- NVIDIA cuFFT Documentation
- stb_image library by Sean Barrett