This project implements a method for detecting AI-generated images by analyzing the fractal properties of the noise residual in the frequency domain.
This tool analyzes images to determine if they are:
- Real photographs (captured by cameras)
- AI-generated images (created by AI models like DALL-E, Midjourney, Stable Diffusion)
Why does this work?
Natural photographs have distinctive noise patterns that AI generators don't perfectly replicate:
- Real images have noise that follows a power-law distribution with spectral exponent β ≈ 1.5-2.5
- AI-generated images often have "too clean" or "too uniform" noise patterns with β outside this range
The algorithm:
- Removes the "main content" (edges, structures) using bilateral filtering
- Analyzes the remaining "noise residual" in the frequency domain
- Measures how quickly power decreases with frequency (spectral exponent β)
- Converts this to a Fractal Dimension (D)
- Classifies based on whether these values match natural patterns
| Metric | Description | Real Image Range | AI-Generated Range |
|---|---|---|---|
| β (beta) | Spectral exponent | 1.5 - 2.5 | < 1.5 or > 2.5 |
| D (Fractal Dimension) | Fractal complexity | 2.0 - 3.0 | < 2.0 or > 3.0 |
| Confidence | Classification certainty | 50-100% | 50-100% |
✅ Real Image (example: photo.jpg):
Beta: 1.85
Fractal Dimension: 2.52
Prediction: Real (confidence: 95%)
❌ AI-Generated Image (example: ai_art.png):
Beta: 1.25
Fractal Dimension: 2.75
Prediction: AI-generated (confidence: 82%)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt# Activate environment first
source venv/bin/activate
# Set Python path
export PYTHONPATH=$PYTHONPATH:$(pwd)/src
# Run analysis
python3 main.py data/image.jpeg --out results/python3 main.py --dir data/ --out results/Look in the results/ folder for:
{filename}_residual.png- The noise residual visualization{filename}_spectrum.png- Log-log PSD plot with fit line
- Shows the "noise" that remains after removing main image content
- Real images have complex, irregular patterns
- AI images may look smoother or have artifacts
- X-axis: Spatial frequency (low to high)
- Y-axis: Power at each frequency
- Green dashed line: Linear fit
- Slope ≈ -β: The steeper the slope, the more "natural" the noise
If the data points follow a straight line, your image has fractal noise characteristics (likely real).
Different images may need different bilateral filter settings:
python3 main.py image.jpg --d 15 --sigma-color 30 --sigma-space 25python3 main.py image.jpg --no-classifyCreate a CSV file labels.csv:
photo1.jpg,Real
photo2.jpg,Real
ai_art1.png,AI-generated
ai_art2.png,AI-generatedThen run:
python3 main.py --dir data/ --ground-truth labels.csvfrom fractal_analysis import (
load_grayscale_image,
adaptive_gamma_correction,
denoise_image,
get_noise_residual,
compute_spectrum,
calculate_fractal_spectrum,
classify_image
)
# Load and process image
img = load_grayscale_image("my_image.jpg")
img_gamma = adaptive_gamma_correction(img)
denoised = denoise_image(img_gamma)
residual = get_noise_residual(img_gamma, denoised)
# Analyze fractal properties
spectrum = compute_spectrum(residual)
freqs, psd1D, beta, D = calculate_fractal_spectrum(spectrum, img.shape)
# Classify
prediction, confidence = classify_image(beta, D)
print(f"Prediction: {prediction} ({confidence:.1%})")Fractal_Analysis/
├── src/fractal_analysis/
│ ├── __init__.py # Package exports
│ ├── preprocessing.py # Gamma correction, denoising
│ ├── analysis.py # FFT, fractal calculations
│ ├── utils.py # Image I/O
│ └── classifier.py # Classification logic
├── main.py # CLI entry point
├── data/ # Input images
├── results/ # Output files
└── requirements.txt # Dependencies
-
Not 100% accurate: This is a heuristic method. Some AI images may be classified as real, and some real images with unusual noise may be classified as AI-generated.
-
Image quality matters: Very noisy or low-quality images may give unreliable results.
-
Multiple factors: AI detection is complex. This method examines just one aspect (noise patterns).
-
Calibrate for your use case: Use
calibrate_thresholds()with your own labeled data for best results.
This method is based on research showing that:
- Natural images have fractal characteristics in their noise
- AI generators often produce images with different statistical properties
- Frequency domain analysis reveals these differences
Key papers:
- "Detecting AI-generated images using frequency domain features"
- "Fractal analysis for digital image forensics"
- Test with your own images
- Collect labeled data (real vs AI-generated)
- Calibrate thresholds using
calibrate_thresholds() - Combine with other detection methods for better accuracy