{"id":37066639,"url":"https://github.com/rehanguha/brisque","last_synced_at":"2026-02-22T15:25:14.763Z","repository":{"id":38441969,"uuid":"177550233","full_name":"rehanguha/brisque","owner":"rehanguha","description":"Blind/Referenceless Image Spatial QUality Evaluator (BRISQUE)","archived":false,"fork":false,"pushed_at":"2025-07-17T05:01:43.000Z","size":1140,"stargazers_count":95,"open_issues_count":3,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-14T09:31:05.612Z","etag":null,"topics":["brisque","computer-vision","cv","image-processing","python","statistical-analysis"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/brisque/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rehanguha.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["rehanguha"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2019-03-25T09:00:38.000Z","updated_at":"2026-01-11T09:21:28.000Z","dependencies_parsed_at":"2024-05-01T08:25:19.356Z","dependency_job_id":"a89f8a8b-2bbc-465e-b310-fdfe3d712630","html_url":"https://github.com/rehanguha/brisque","commit_stats":{"total_commits":42,"total_committers":3,"mean_commits":14.0,"dds":0.04761904761904767,"last_synced_commit":"bfe6870c74eb40c8b8609f79dad26a4d98325a0b"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/rehanguha/brisque","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehanguha%2Fbrisque","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehanguha%2Fbrisque/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehanguha%2Fbrisque/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehanguha%2Fbrisque/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rehanguha","download_url":"https://codeload.github.com/rehanguha/brisque/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehanguha%2Fbrisque/sbom","scorecard":{"id":769184,"data":{"date":"2025-08-18","repo":{"name":"github.com/rehanguha/brisque","commit":"4337ae4e6bee20fe21fafd60c9dd228fe09dafff"},"scorecard":{"version":"v5.2.1-41-g40576783","commit":"40576783fda6698350fcbbeaea760ff827433034"},"score":4.5,"checks":[{"name":"Maintained","score":6,"reason":"7 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":1,"reason":"Found 3/28 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/python-app.yml:1","Warn: no topLevel permission defined: .github/workflows/python-publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/rehanguha/brisque/python-app.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/rehanguha/brisque/python-app.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-publish.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/rehanguha/brisque/python-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-publish.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/rehanguha/brisque/python-publish.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/python-publish.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/python-publish.yml:29","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   5 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/python-publish.yml:16"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#packaging"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T01:46:05.536Z","repository_id":38441969,"created_at":"2025-08-23T01:46:05.536Z","updated_at":"2025-08-23T01:46:05.536Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29716987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T15:10:41.462Z","status":"ssl_error","status_checked_at":"2026-02-22T15:10:04.636Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brisque","computer-vision","cv","image-processing","python","statistical-analysis"],"created_at":"2026-01-14T07:49:22.217Z","updated_at":"2026-02-22T15:25:14.755Z","avatar_url":"https://github.com/rehanguha.png","language":"Python","funding_links":["https://github.com/sponsors/rehanguha"],"categories":[],"sub_categories":[],"readme":"# Blind/Referenceless Image Spatial Quality Evaluator (BRISQUE) \n\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11104461.svg)](https://doi.org/10.5281/zenodo.11104461)\n\nBRISQUE is a no-reference image quality score.\n\n## 🆕 What's New in v0.2.0\n\n### Flexible OpenCV Dependencies\n\nStarting with v0.2.0, BRISQUE no longer forces a specific OpenCV variant. This allows you to use whichever OpenCV package best suits your environment.\n\n| OpenCV Variant | Best For |\n|----------------|----------|\n| `opencv-python` | Desktop applications with GUI support |\n| `opencv-python-headless` | Servers, Docker, CI/CD (no GUI) |\n| `opencv-contrib-python` | Desktop with extra OpenCV modules |\n| `opencv-contrib-python-headless` | Servers with extra modules |\n\n**Why this change?**\n- OpenCV variants are mutually exclusive - installing one removes others\n- Previous versions required `opencv-python`, causing conflicts for users with different variants\n- Server/headless environments don't need GUI dependencies from `opencv-python`\n\n### Installation Options\n\n**Option 1: Install with OpenCV (Recommended for new users)**\n```bash\npip install brisque[opencv-python]              # Desktop applications\npip install brisque[opencv-python-headless]     # Servers / Docker (recommended)\npip install brisque[opencv-contrib-python]      # With extra OpenCV modules\npip install brisque[opencv-contrib-python-headless]  # Servers with extra modules\n```\n\n**Option 2: Use existing OpenCV installation**\n```bash\n# If you already have OpenCV installed\npip install opencv-python-headless   # or any variant you prefer\npip install brisque                  # will use your existing OpenCV\n```\n\n**Option 3: Install OpenCV separately (for Docker/corporate environments)**\n```bash\n# In your Dockerfile or controlled environment\npip install opencv-python-headless\npip install brisque  # Uses the pre-installed OpenCV\n```\n\n\u003e ⚠️ **Note**: BRISQUE requires OpenCV to function. If you install brisque without OpenCV, you'll get a helpful error message with installation instructions.\n\n### Migration from v0.1.x\n\nIf you're upgrading from v0.1.x or earlier:\n\n**Scenario A: Standard desktop usage (no changes needed)**\n```bash\n# Your existing OpenCV will be detected and used\npip install --upgrade brisque\n```\n\n**Scenario B: Clean install or server environment**\n```bash\n# Uninstall old version\npip uninstall brisque\n\n# Install with your preferred OpenCV variant\npip install brisque[opencv-python-headless]  # Recommended for servers\n```\n\n**Scenario C: Docker/CI environments**\n```dockerfile\n# In your Dockerfile\nRUN pip install opencv-python-headless\nRUN pip install brisque\n```\n\n**What changed:**\n- v0.1.x: `pip install brisque` automatically installed `opencv-python`\n- v0.2.0: OpenCV is no longer auto-installed - you choose your variant\n\n**Code compatibility:** No changes needed! Your existing code continues to work:\n```python\nfrom brisque import BRISQUE  # Still works exactly the same\nobj = BRISQUE(url=False)\nscore = obj.score(image)\n```\n\n---\n\n\n## Installation\n\n**Quick Start:**\n```bash\n# For servers/Docker (recommended):\npip install brisque[opencv-python-headless]\n\n# For desktop applications:\npip install brisque[opencv-python]\n```\n\n**See the [Installation Options](#installation-options) section above for more details.**\n\n## Usage\n\n### 1. Image Quality Assessment on Local Images\n\n```python\nfrom brisque import BRISQUE\n\nobj = BRISQUE(url=False)\nobj.score(\"\u003cNdarray of the Image\u003e\")\n```\n\n### 2. Image Quality Assessment on Web Images\n\n```python\nfrom brisque import BRISQUE\n\nobj = BRISQUE(url=True)\nobj.score(\"\u003cURL for the Image\u003e\")\n```\n\n### 3. Using Custom Trained Models\n\n```python\nfrom brisque import BRISQUE\n\nobj = BRISQUE(url=False, model_path={\n    \"svm\": \"path/to/custom_svm.txt\",\n    \"normalize\": \"path/to/custom_normalize.pickle\"\n})\nobj.score(image)\n```\n\n## Examples\n\n### Local Image\n\n```python\nfrom brisque import BRISQUE\nimport numpy as np\nfrom PIL import Image\n\nimg_path = \"brisque/tests/sample-image.jpg\"\nimg = Image.open(img_path)\nndarray = np.asarray(img)\n\nobj = BRISQUE(url=False)\nobj.score(img=ndarray)\n```\n\nOutput:\n```\n34.84883848208594\n```\n\n### URL\n\n```python\nfrom brisque import BRISQUE\n\nURL = \"https://www.mathworks.com/help/examples/images/win64/CalculateBRISQUEScoreUsingCustomFeatureModelExample_01.png\"\n\nobj = BRISQUE(url=True)\nobj.score(URL)\n```\n\nOutput:\n```\n71.73427549219988\n```\n\n---\n\n## Training Custom Models\n\nThe `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.\n\n### When to Train a Custom Model\n\n- Domain-specific images (medical, satellite, underwater, etc.)\n- Specific distortion types not well-represented in the default model\n- Custom quality scales or scoring methodologies\n- Research purposes requiring reproducible quality assessment\n\n---\n\n## Step-by-Step Guide: Training a Custom BRISQUE Model\n\n### Step 1: Install the Package\n\n```bash\npip install brisque\n```\n\n### Step 2: Prepare Your Dataset\n\nOrganize your images and quality scores. You'll need:\n- A directory containing your images\n- A CSV file with image filenames and their quality scores\n\n**Dataset structure:**\n```\nmy_dataset/\n├── images/\n│   ├── img_001.jpg\n│   ├── img_002.jpg\n│   ├── img_003.jpg\n│   └── ...\n└── scores.csv\n```\n\n**CSV format (scores.csv):**\n```csv\nimage,score\nimg_001.jpg,23.5\nimg_002.jpg,45.2\nimg_003.jpg,31.8\nimg_004.jpg,12.1\n...\n```\n\n\u003e **Note on Quality Scores**: Lower scores should indicate better quality. Use consistent scoring methodology across all images. Common scales include:\n\u003e - MOS (Mean Opinion Score): 1-5 scale\n\u003e - DMOS (Differential MOS): 0-100 scale\n\u003e - Custom scales specific to your application\n\n### Step 3: Create a Training Script\n\nCreate a file called `train_brisque.py`:\n\n```python\nfrom brisque import BRISQUETrainer, BRISQUE\nimport numpy as np\n\n# Initialize the trainer\ntrainer = BRISQUETrainer()\n\n# Load your dataset\ntrainer.add_dataset(\n    image_dir=\"my_dataset/images\",\n    scores_file=\"my_dataset/scores.csv\",\n    image_column=\"image\",    # column name for image filenames\n    score_column=\"score\"     # column name for quality scores\n)\n\nprint(f\"Loaded {len(trainer.features)} images\")\n\n# Train the model with custom SVM parameters\ntrainer.train(\n    svm_c=10.0,           # Regularization (higher = less tolerance for errors)\n    svm_gamma=0.1,        # RBF kernel coefficient\n    svm_epsilon=0.1,      # Epsilon-tube for SVR\n    kernel=\"rbf\"          # Kernel type: \"rbf\", \"linear\", \"poly\", or \"sigmoid\"\n)\n\n# Save the trained model\ntrainer.save_model(\n    svm_path=\"custom_model/svm.txt\",\n    norm_path=\"custom_model/normalize.pickle\"\n)\n\nprint(\"Model saved successfully!\")\n```\n\n### Step 4: Run the Training\n\n```bash\npython train_brisque.py\n```\n\n### Step 5: Evaluate the Model (Optional)\n\nEvaluate your model on a separate test set:\n\n```python\nfrom brisque import BRISQUETrainer\nimport numpy as np\nfrom PIL import Image\n\n# After training, evaluate on test data\ntest_images = [np.array(Image.open(f\"test_images/img_{i}.jpg\")) for i in range(10)]\ntest_scores = [25.3, 42.1, 18.9, ...]  # ground truth scores\n\nmetrics = trainer.evaluate(test_images, test_scores)\n\nprint(f\"RMSE:  {metrics['rmse']:.4f}\")   # Root Mean Square Error (lower is better)\nprint(f\"PLCC:  {metrics['plcc']:.4f}\")   # Pearson correlation (closer to 1 is better)\nprint(f\"SROCC: {metrics['srocc']:.4f}\")  # Spearman correlation (closer to 1 is better)\n```\n\n### Step 6: Use Your Trained Model\n\n```python\nfrom brisque import BRISQUE\nimport numpy as np\nfrom PIL import Image\n\n# Load your custom model\nobj = BRISQUE(url=False, model_path={\n    \"svm\": \"custom_model/svm.txt\",\n    \"normalize\": \"custom_model/normalize.pickle\"\n})\n\n# Score a new image\nimage = np.array(Image.open(\"new_image.jpg\"))\nquality_score = obj.score(image)\n\nprint(f\"Quality Score: {quality_score}\")\n```\n\n### Step 7: Integrate into Your Pipeline\n\n```python\nfrom brisque import BRISQUE\nimport numpy as np\n\n# Initialize once at application startup\nbrisque = BRISQUE(url=False, model_path={\n    \"svm\": \"custom_model/svm.txt\",\n    \"normalize\": \"custom_model/normalize.pickle\"\n})\n\n# Use throughout your application\ndef assess_image_quality(image_array: np.ndarray) -\u003e float:\n    \"\"\"Assess image quality using custom BRISQUE model.\"\"\"\n    return brisque.score(image_array)\n\n# Example usage\nfor image_path in image_paths:\n    img = np.array(Image.open(image_path))\n    score = assess_image_quality(img)\n    print(f\"{image_path}: {score:.2f}\")\n```\n\n---\n\n## Alternative: Training with Individual Images\n\nIf you prefer to add images individually instead of from a CSV:\n\n```python\nfrom brisque import BRISQUETrainer\nimport numpy as np\nfrom PIL import Image\n\ntrainer = BRISQUETrainer()\n\n# Add images one by one\nimages = [\"img1.jpg\", \"img2.jpg\", \"img3.jpg\"]\nscores = [23.5, 45.2, 31.8]\n\nfor img_path, score in zip(images, scores):\n    img = np.array(Image.open(img_path))\n    trainer.add_image(img, score)\n\n# Train and save\ntrainer.train()\ntrainer.save_model(\"custom_svm.txt\", \"custom_normalize.pickle\")\n```\n\n---\n\n## Training Tips\n\n### Data Requirements\n| Dataset Size | Expected Performance |\n|--------------|---------------------|\n| 2-10 images | Minimal - for testing only |\n| 50-100 images | Basic functionality |\n| 200+ images | Good performance |\n| 500+ images | Optimal performance |\n\n### SVM Parameter Tuning\n\n| Parameter | Effect | Typical Range |\n|-----------|--------|---------------|\n| `svm_c` | Regularization strength | 0.1 - 100 |\n| `svm_gamma` | RBF kernel width | 0.001 - 1 |\n| `svm_epsilon` | Tolerance for errors | 0.01 - 0.5 |\n| `kernel` | Kernel function | \"rbf\" (default), \"linear\" |\n\n### Best Practices\n\n1. **Normalize scores**: Ensure all scores use the same scale\n2. **Balance quality levels**: Include images across the quality spectrum\n3. **Use representative images**: Training images should match your target domain\n4. **Validate on held-out data**: Keep 20% of data for testing\n5. **Experiment with parameters**: Try different `svm_c` and `svm_gamma` values\n\n---\n\n## API Reference\n\n### BRISQUE Class\n\n```python\nBRISQUE(url=False, model_path=None)\n```\n\n**Parameters:**\n- `url` (bool): If True, accept URLs in `score()`. If False, accept numpy arrays. Default: False.\n- `model_path` (dict, optional): Custom model paths with keys:\n  - `\"svm\"`: Path to SVM model file\n  - `\"normalize\"`: Path to normalization parameters file\n\n**Methods:**\n- `score(img)`: Compute quality score for an image\n\n### BRISQUETrainer Class\n\n```python\nBRISQUETrainer()\n```\n\n**Methods:**\n- `add_image(image, score)`: Add single image with quality score\n- `add_dataset(image_dir, scores_file, image_column=\"image\", score_column=\"score\")`: Load from directory and CSV\n- `train(svm_c=1.0, svm_gamma=0.1, svm_epsilon=0.1, kernel=\"rbf\")`: Train the model\n- `save_model(svm_path, norm_path)`: Save trained model\n- `evaluate(images, scores)`: Evaluate model, returns dict with RMSE, PLCC, SROCC\n- `clear()`: Clear all data and model\n\n---\n\n## Testing\n\nRun the test suite:\n\n```bash\n# Run all tests\npytest brisque/tests/ -v\n\n# Run specific test file\npytest brisque/tests/test_trainer.py -v\n\n# Run with coverage\npytest brisque/tests/ -v --cov=brisque\n```\n\n---\n\n## How BRISQUE Works\n\nBRISQUE extracts 36 features from each image:\n- 18 features from the original scale (MSCN coefficients)\n- 18 features from the half-scale (downsampled image)\n\nFeatures are based on:\n- Mean Subtracted Contrast Normalized (MSCN) coefficients\n- Pairwise products (horizontal, vertical, diagonal)\n- Asymmetric Generalized Gaussian Distribution fitting\n\nThe SVM regression model maps these features to quality scores.\n\n---\n\n## Citation\n\nIf you use this package in your research, please cite:\n\n```bibtex\n@software{brisque2024,\n  author = {Guha, Rehan},\n  title = {BRISQUE: Blind/Referenceless Image Spatial Quality Evaluator},\n  year = {2024},\n  doi = {10.5281/zenodo.11104461}\n}\n```\n\n## License\n\nApache-2.0\n\n ---\n\nA good place to know how BRISQUE works : [LearnOpenCV](https://learnopencv.com/image-quality-assessment-brisque/)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frehanguha%2Fbrisque","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frehanguha%2Fbrisque","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frehanguha%2Fbrisque/lists"}