Image Blur Detection
A pure Dart/Flutter package to detect blur, brightness, and contrast issues in images with configurable thresholds.
This package is especially useful for:
- Card scanning (ID cards, credit cards, driver's licenses)
- Document scanning
- Photo capture validation
- Any scenario where image quality needs to be validated before processing
Demo

Features
- Blur Detection: Uses Laplacian variance algorithm to detect blurry images
- Brightness Analysis: Detects underexposed (too dark) or overexposed (too bright) images
- Contrast Analysis: Detects low contrast images using histogram-based standard deviation
- Configurable Thresholds: Easily adjust sensitivity for your use case
- Preset Configurations: Ready-to-use presets for common scenarios
- Pure Dart: No native dependencies, works on all platforms
Installation
Add this to your pubspec.yaml:
dependencies:
image_blur_detection: ^1.0.0
Then run:
dart pub get
Quick Start
import 'package:image_blur_detection/image_blur_detection.dart';
// Simple usage with defaults
final validator = ImageQualityValidator();
final result = await validator.validate(imageBytes);
if (result.isValid) {
// Proceed with image processing
} else {
print('Issues: ${result.issues}');
}
Usage
Basic Validation
import 'dart:io';
import 'package:image_blur_detection/image_blur_detection.dart';
// Read image from file
final file = File('path/to/image.jpg');
final imageBytes = await file.readAsBytes();
// Validate the image
final validator = ImageQualityValidator();
final result = await validator.validate(imageBytes);
if (result.isValid) {
print('Image quality is good!');
} else {
print('Issues found: ${result.issues}');
print('Primary issue: ${result.errorMessage}');
}
Using Preset Configurations
The package includes preset configurations optimized for common use cases:
// Card scanning (relaxed thresholds for handheld scanning)
final cardValidator = ImageQualityValidator(
config: QualityConfig.cardScanning,
);
// Document scanning (moderate thresholds)
final docValidator = ImageQualityValidator(
config: QualityConfig.documentScanning,
);
// Photo capture (stricter blur detection)
final photoValidator = ImageQualityValidator(
config: QualityConfig.photoCapture,
);
// Relaxed (for challenging conditions)
final relaxedValidator = ImageQualityValidator(
config: QualityConfig.relaxed,
);
// Strict (for high quality requirements)
final strictValidator = ImageQualityValidator(
config: QualityConfig.strict,
);
Custom Configuration
final customValidator = ImageQualityValidator(
config: QualityConfig(
blurThreshold: 150.0, // Higher = stricter blur detection
minBrightness: 50.0, // 0-255 scale
maxBrightness: 200.0, // 0-255 scale
minContrast: 60.0, // Higher = require more contrast
),
);
// Or modify an existing config
final modifiedConfig = QualityConfig.cardScanning.copyWith(
blurThreshold: 100.0, // Override just the blur threshold
);
Individual Quality Checks
You can also perform individual checks if you only need specific validation:
final validator = ImageQualityValidator();
// Check only blur
final blurResult = validator.checkBlur(imageBytes);
print('Is blurry: ${blurResult.isBlurry}');
print('Variance: ${blurResult.variance}');
// Check only brightness
final brightnessResult = validator.checkBrightness(imageBytes);
print('Level: ${brightnessResult.level}');
print('Average: ${brightnessResult.averageBrightness}');
// Check only contrast
final contrastResult = validator.checkContrast(imageBytes);
print('Has good contrast: ${contrastResult.hasGoodContrast}');
print('Score: ${contrastResult.contrastScore}');
Using Detectors Directly
For more control, you can use the individual detectors directly:
// Blur detection
const blurDetector = BlurDetector(threshold: 120.0);
final blurResult = blurDetector.detect(imageBytes);
// Brightness analysis
const brightnessAnalyzer = BrightnessAnalyzer(
minBrightness: 45.0,
maxBrightness: 210.0,
);
final brightnessResult = brightnessAnalyzer.analyze(imageBytes);
// Contrast analysis
const contrastAnalyzer = ContrastAnalyzer(minContrast: 55.0);
final contrastResult = contrastAnalyzer.analyze(imageBytes);
Working with Pre-decoded Images
If you already have a decoded image (using the image package), you can use the FromImage methods to avoid re-decoding:
import 'package:image/image.dart' as img;
final image = img.decodeImage(imageBytes);
final validator = ImageQualityValidator();
final result = await validator.validateFromImage(image);
// Or with individual detectors
final blurResult = blurDetector.detectFromImage(image);
final brightnessResult = brightnessAnalyzer.analyzeFromImage(image);
final contrastResult = contrastAnalyzer.analyzeFromImage(image);
Threshold Guidelines
Blur Threshold (Laplacian Variance)
The blur threshold represents the minimum Laplacian variance for a sharp image. Higher values require sharper images.
| Use Case | Recommended Range | Description |
|---|---|---|
| Relaxed | 50-80 | For low-quality cameras or challenging conditions |
| Card Scanning | 80-150 | Standard handheld card scanning |
| Document Scanning | 100-200 | Text documents where sharpness matters |
| Photo Capture | 150-300 | When high quality photos are required |
| Strict | 250-500 | Professional quality requirements |
Brightness (0-255 Scale)
| Setting | Too Dark | Too Bright | Description |
|---|---|---|---|
| Relaxed | < 25 | > 240 | Very permissive |
| Standard | < 40 | > 220 | General purpose |
| Strict | < 50 | > 200 | Well-lit environments |
Contrast (Standard Deviation)
The contrast score is the standard deviation of pixel luminance values. Higher values indicate more contrast.
| Use Case | Minimum Score | Description |
|---|---|---|
| Relaxed | 30-40 | Accept low contrast images |
| Standard | 50-60 | General purpose |
| Strict | 65+ | Require good contrast |
API Reference
Classes
ImageQualityValidator
Main validator that combines all quality checks.
BlurDetector
Detects blur using Laplacian variance method.
BrightnessAnalyzer
Analyzes image brightness/exposure.
ContrastAnalyzer
Analyzes image contrast.
QualityConfig
Configuration for all quality thresholds.
Result Classes
QualityResult
Combined result with isValid, issues, errorMessage, and individual results.
BlurResult
Contains isBlurry, variance, confidence, and threshold.
BrightnessResult
Contains level (tooDark/optimal/tooBright), averageBrightness, and thresholds.
ContrastResult
Contains hasGoodContrast, contrastScore, and threshold.
How It Works
Blur Detection (Laplacian Variance)
- Convert image to grayscale
- Apply Laplacian filter (edge detection)
- Calculate variance of the result
- Sharp images have high variance (many strong edges)
- Blurry images have low variance (edges are smoothed)
Brightness Analysis
- Calculate the luminance of each pixel
- Compute the average luminance
- Compare against min/max thresholds
Contrast Analysis
- Calculate the luminance of each pixel
- Compute the standard deviation of luminance values
- Higher standard deviation = more contrast
Example
See the example for a complete demonstration of all features.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Libraries
- image_blur_detection
- A Flutter/Dart package to detect blur, brightness, and contrast issues in images with configurable thresholds.