BRISQUE is a no-reference image quality score.
Starting with v0.2.0, BRISQUE no longer forces a specific OpenCV variant. This allows you to use whichever OpenCV package best suits your environment.
| OpenCV Variant | Best For |
|---|---|
opencv-python |
Desktop applications with GUI support |
opencv-python-headless |
Servers, Docker, CI/CD (no GUI) |
opencv-contrib-python |
Desktop with extra OpenCV modules |
opencv-contrib-python-headless |
Servers with extra modules |
Why this change?
- OpenCV variants are mutually exclusive - installing one removes others
- Previous versions required
opencv-python, causing conflicts for users with different variants - Server/headless environments don't need GUI dependencies from
opencv-python
Option 1: Install with OpenCV (Recommended for new users)
pip install brisque[opencv-python] # Desktop applications
pip install brisque[opencv-python-headless] # Servers / Docker (recommended)
pip install brisque[opencv-contrib-python] # With extra OpenCV modules
pip install brisque[opencv-contrib-python-headless] # Servers with extra modulesOption 2: Use existing OpenCV installation
# If you already have OpenCV installed
pip install opencv-python-headless # or any variant you prefer
pip install brisque # will use your existing OpenCVOption 3: Install OpenCV separately (for Docker/corporate environments)
# In your Dockerfile or controlled environment
pip install opencv-python-headless
pip install brisque # Uses the pre-installed OpenCV
⚠️ Note: BRISQUE requires OpenCV to function. If you install brisque without OpenCV, you'll get a helpful error message with installation instructions.
If you're upgrading from v0.1.x or earlier:
Scenario A: Standard desktop usage (no changes needed)
# Your existing OpenCV will be detected and used
pip install --upgrade brisqueScenario B: Clean install or server environment
# Uninstall old version
pip uninstall brisque
# Install with your preferred OpenCV variant
pip install brisque[opencv-python-headless] # Recommended for serversScenario C: Docker/CI environments
# In your Dockerfile
RUN pip install opencv-python-headless
RUN pip install brisqueWhat changed:
- v0.1.x:
pip install brisqueautomatically installedopencv-python - v0.2.0: OpenCV is no longer auto-installed - you choose your variant
Code compatibility: No changes needed! Your existing code continues to work:
from brisque import BRISQUE # Still works exactly the same
obj = BRISQUE(url=False)
score = obj.score(image)Quick Start:
# For servers/Docker (recommended):
pip install brisque[opencv-python-headless]
# For desktop applications:
pip install brisque[opencv-python]See the Installation Options section above for more details.
from brisque import BRISQUE
obj = BRISQUE(url=False)
obj.score("<Ndarray of the Image>")from brisque import BRISQUE
obj = BRISQUE(url=True)
obj.score("<URL for the Image>")from brisque import BRISQUE
obj = BRISQUE(url=False, model_path={
"svm": "path/to/custom_svm.txt",
"normalize": "path/to/custom_normalize.pickle"
})
obj.score(image)from brisque import BRISQUE
import numpy as np
from PIL import Image
img_path = "brisque/tests/sample-image.jpg"
img = Image.open(img_path)
ndarray = np.asarray(img)
obj = BRISQUE(url=False)
obj.score(img=ndarray)Output:
34.84883848208594
from brisque import BRISQUE
URL = "https://www.mathworks.com/help/examples/images/win64/CalculateBRISQUEScoreUsingCustomFeatureModelExample_01.png"
obj = BRISQUE(url=True)
obj.score(URL)Output:
71.73427549219988
The BRISQUETrainer class allows you to train custom BRISQUE models using your own image quality datasets. This is useful when you need a model tailored to specific image types or distortion patterns.
- Domain-specific images (medical, satellite, underwater, etc.)
- Specific distortion types not well-represented in the default model
- Custom quality scales or scoring methodologies
- Research purposes requiring reproducible quality assessment
pip install brisqueOrganize your images and quality scores. You'll need:
- A directory containing your images
- A CSV file with image filenames and their quality scores
Dataset structure:
my_dataset/
├── images/
│ ├── img_001.jpg
│ ├── img_002.jpg
│ ├── img_003.jpg
│ └── ...
└── scores.csv
CSV format (scores.csv):
image,score
img_001.jpg,23.5
img_002.jpg,45.2
img_003.jpg,31.8
img_004.jpg,12.1
...Note on Quality Scores: Lower scores should indicate better quality. Use consistent scoring methodology across all images. Common scales include:
- MOS (Mean Opinion Score): 1-5 scale
- DMOS (Differential MOS): 0-100 scale
- Custom scales specific to your application
Create a file called train_brisque.py:
from brisque import BRISQUETrainer, BRISQUE
import numpy as np
# Initialize the trainer
trainer = BRISQUETrainer()
# Load your dataset
trainer.add_dataset(
image_dir="my_dataset/images",
scores_file="my_dataset/scores.csv",
image_column="image", # column name for image filenames
score_column="score" # column name for quality scores
)
print(f"Loaded {len(trainer.features)} images")
# Train the model with custom SVM parameters
trainer.train(
svm_c=10.0, # Regularization (higher = less tolerance for errors)
svm_gamma=0.1, # RBF kernel coefficient
svm_epsilon=0.1, # Epsilon-tube for SVR
kernel="rbf" # Kernel type: "rbf", "linear", "poly", or "sigmoid"
)
# Save the trained model
trainer.save_model(
svm_path="custom_model/svm.txt",
norm_path="custom_model/normalize.pickle"
)
print("Model saved successfully!")python train_brisque.pyEvaluate your model on a separate test set:
from brisque import BRISQUETrainer
import numpy as np
from PIL import Image
# After training, evaluate on test data
test_images = [np.array(Image.open(f"test_images/img_{i}.jpg")) for i in range(10)]
test_scores = [25.3, 42.1, 18.9, ...] # ground truth scores
metrics = trainer.evaluate(test_images, test_scores)
print(f"RMSE: {metrics['rmse']:.4f}") # Root Mean Square Error (lower is better)
print(f"PLCC: {metrics['plcc']:.4f}") # Pearson correlation (closer to 1 is better)
print(f"SROCC: {metrics['srocc']:.4f}") # Spearman correlation (closer to 1 is better)from brisque import BRISQUE
import numpy as np
from PIL import Image
# Load your custom model
obj = BRISQUE(url=False, model_path={
"svm": "custom_model/svm.txt",
"normalize": "custom_model/normalize.pickle"
})
# Score a new image
image = np.array(Image.open("new_image.jpg"))
quality_score = obj.score(image)
print(f"Quality Score: {quality_score}")from brisque import BRISQUE
import numpy as np
# Initialize once at application startup
brisque = BRISQUE(url=False, model_path={
"svm": "custom_model/svm.txt",
"normalize": "custom_model/normalize.pickle"
})
# Use throughout your application
def assess_image_quality(image_array: np.ndarray) -> float:
"""Assess image quality using custom BRISQUE model."""
return brisque.score(image_array)
# Example usage
for image_path in image_paths:
img = np.array(Image.open(image_path))
score = assess_image_quality(img)
print(f"{image_path}: {score:.2f}")If you prefer to add images individually instead of from a CSV:
from brisque import BRISQUETrainer
import numpy as np
from PIL import Image
trainer = BRISQUETrainer()
# Add images one by one
images = ["img1.jpg", "img2.jpg", "img3.jpg"]
scores = [23.5, 45.2, 31.8]
for img_path, score in zip(images, scores):
img = np.array(Image.open(img_path))
trainer.add_image(img, score)
# Train and save
trainer.train()
trainer.save_model("custom_svm.txt", "custom_normalize.pickle")| Dataset Size | Expected Performance |
|---|---|
| 2-10 images | Minimal - for testing only |
| 50-100 images | Basic functionality |
| 200+ images | Good performance |
| 500+ images | Optimal performance |
| Parameter | Effect | Typical Range |
|---|---|---|
svm_c |
Regularization strength | 0.1 - 100 |
svm_gamma |
RBF kernel width | 0.001 - 1 |
svm_epsilon |
Tolerance for errors | 0.01 - 0.5 |
kernel |
Kernel function | "rbf" (default), "linear" |
- Normalize scores: Ensure all scores use the same scale
- Balance quality levels: Include images across the quality spectrum
- Use representative images: Training images should match your target domain
- Validate on held-out data: Keep 20% of data for testing
- Experiment with parameters: Try different
svm_candsvm_gammavalues
BRISQUE(url=False, model_path=None)Parameters:
url(bool): If True, accept URLs inscore(). If False, accept numpy arrays. Default: False.model_path(dict, optional): Custom model paths with keys:"svm": Path to SVM model file"normalize": Path to normalization parameters file
Methods:
score(img): Compute quality score for an image
BRISQUETrainer()Methods:
add_image(image, score): Add single image with quality scoreadd_dataset(image_dir, scores_file, image_column="image", score_column="score"): Load from directory and CSVtrain(svm_c=1.0, svm_gamma=0.1, svm_epsilon=0.1, kernel="rbf"): Train the modelsave_model(svm_path, norm_path): Save trained modelevaluate(images, scores): Evaluate model, returns dict with RMSE, PLCC, SROCCclear(): Clear all data and model
Run the test suite:
# Run all tests
pytest brisque/tests/ -v
# Run specific test file
pytest brisque/tests/test_trainer.py -v
# Run with coverage
pytest brisque/tests/ -v --cov=brisqueBRISQUE extracts 36 features from each image:
- 18 features from the original scale (MSCN coefficients)
- 18 features from the half-scale (downsampled image)
Features are based on:
- Mean Subtracted Contrast Normalized (MSCN) coefficients
- Pairwise products (horizontal, vertical, diagonal)
- Asymmetric Generalized Gaussian Distribution fitting
The SVM regression model maps these features to quality scores.
If you use this package in your research, please cite:
@software{brisque2024,
author = {Guha, Rehan},
title = {BRISQUE: Blind/Referenceless Image Spatial Quality Evaluator},
year = {2024},
doi = {10.5281/zenodo.11104461}
}Apache-2.0
A good place to know how BRISQUE works : LearnOpenCV