Metadata-Version: 2.4
Name: imageguard
Version: 0.1.0
Summary: Validate images before AI pipelines
License: MIT
Project-URL: Homepage, https://github.com/vipul510-web/imageguard
Project-URL: Repository, https://github.com/vipul510-web/imageguard
Project-URL: Bug Tracker, https://github.com/vipul510-web/imageguard/issues
Keywords: image,validation,quality,ai,pipeline,ocr,machine-learning
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: opencv-python>=4.8
Requires-Dist: numpy>=1.24
Requires-Dist: scikit-image>=0.21
Provides-Extra: url
Requires-Dist: requests>=2.28; extra == "url"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"

# imageguard

**Validate images before AI pipelines.**

[![PyPI version](https://img.shields.io/badge/pypi-v0.1.0-blue)](https://pypi.org/project/imageguard/)
[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://pypi.org/project/imageguard/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Used in production](https://img.shields.io/badge/used%20in%20production-changeimageto.com-brightgreen)](https://www.changeimageto.com/image-quality-checker.html)

imageguard is a lightweight Python library that checks whether an image is good enough to feed into an AI pipeline — OCR, background removal, upscaling, dataset training, or any model that is sensitive to image quality.

**No image-processing knowledge required.** Pass in a path. Get back a decision.

```python
from imageguard import validate

result = validate("photo.jpg")

if not result.ok:
    print("Reject:", result.reason)  # "blurry"
else:
    print("Score:", result.score)    # 0.87
```

> **Used in production at [changeimageto.com](https://www.changeimageto.com/image-quality-checker.html)** — the image quality checker tool that processes thousands of images per day.

---

## Install

```bash
pip install imageguard
```

For URL support (optional):

```bash
pip install "imageguard[url]"
```

---

## The result object

```python
result.ok        # bool   – True if the image passes all checks
result.reason    # str    – primary issue (empty when ok=True)
result.issues    # list   – every detected issue
result.score     # float  – 0.0 (worst) → 1.0 (best)
```

### Possible issues

| Value | Meaning |
|---|---|
| `blurry` | Image is out of focus |
| `low_resolution` | Too few pixels for reliable processing |
| `noisy` | Excessive visual noise |
| `pixelated` | Block artefacts or aggressive upscaling |
| `compressed` | Severe JPEG compression artefacts |
| `underexposed` | Image is too dark |
| `overexposed` | Image is too bright / washed out |
| `clipped` | Large portions are pure black or white |
| `bad_exposure` | General lighting issue |

---

## Input formats

`validate()` accepts a **file path**, a **URL**, or a **numpy array**:

```python
from imageguard import validate
import numpy as np

# File path
result = validate("photo.jpg")
result = validate(Path("photo.png"))

# URL (requires: pip install "imageguard[url]")
result = validate("https://example.com/product.jpg")

# Numpy array (RGB, uint8)
arr = np.zeros((480, 640, 3), dtype=np.uint8)
result = validate(arr)
```

---

## Use cases

### OCR pre-check

```python
from imageguard import validate

result = validate("scan.png", thresholds={"blur_score": 60.0, "resolution_score": 70.0})

if not result.ok:
    raise ValueError(f"Document quality too low for OCR: {result.reason}")

text = ocr_engine.read(scan_path)
```

### Dataset cleaning

```python
from pathlib import Path
from imageguard import validate

accepted, rejected = [], []

for img_path in Path("raw_dataset/").glob("**/*.jpg"):
    result = validate(img_path)
    (accepted if result.ok else rejected).append(img_path)

print(f"Accepted {len(accepted)}, rejected {len(rejected)}")
```

### E-commerce product photo gate

```python
from imageguard import validate

def before_background_removal(image_path: str) -> None:
    result = validate(image_path)
    if result.score < 0.6:
        raise ValueError(
            f"Image quality too low (score {result.score:.2f}): {result.issues}"
        )
    # proceed to AI service…
```

### CI/CD image quality gate (GitHub Actions)

```yaml
- name: Validate image assets
  run: |
    pip install imageguard
    python -c "
    from pathlib import Path
    from imageguard import validate
    import sys
    failures = [(p, validate(p)) for p in Path('assets/').rglob('*.jpg') if not validate(p).ok]
    if failures:
        for p, r in failures: print(f'FAIL {p.name}: {r.reason} ({r.score:.2f})')
        sys.exit(1)
    "
```

---

## Custom thresholds

```python
from imageguard import validate, DEFAULT_THRESHOLDS

print(DEFAULT_THRESHOLDS)
# {'blur_score': 40.0, 'noise_score': 30.0, 'compression_score': 50.0,
#  'pixelation_score': 50.0, 'exposure_score': 40.0,
#  'resolution_score': 60.0, 'overall_score': 40.0}

# Stricter blur check for OCR
result = validate("scan.jpg", thresholds={"blur_score": 60.0})

# More lenient resolution for thumbnails
result = validate("thumb.jpg", thresholds={"resolution_score": 30.0})
```

---

## How it works

imageguard computes six quality signals using OpenCV and scikit-image:

| Signal | Method |
|---|---|
| **Blur** | Laplacian variance + Tenengrad gradient energy, normalised by texture |
| **Noise** | SNR + high-pass filter residual on flat regions |
| **Resolution** | Pixel count with aspect ratio penalty |
| **Exposure** | Histogram balance + entropy + RMS contrast |
| **Compression** | 8×8 border energy ratio (blockiness) |
| **Pixelation** | FFT grid harmonic energy + SSIM round-trip |

All signals are normalised to 0–100. The final `score` (0–1) is a weighted combination with per-issue penalties.

---

## Dependencies

| Package | Purpose |
|---|---|
| `opencv-python` | Image loading and signal computation |
| `numpy` | Array maths |
| `scikit-image` | SSIM for pixelation check |
| `requests` *(optional)* | URL image loading |

---

## Learn more

- [Try the online image quality checker](https://www.changeimageto.com/image-quality-checker.html) — no code needed
- [Why AI pipelines fail on bad images](https://www.changeimageto.com/blog/why-ai-pipelines-fail-on-bad-images.html)
- [How to filter blurry images before OCR](https://www.changeimageto.com/blog/how-to-filter-blurry-images-before-ocr.html)
- [Image validation for machine learning datasets](https://www.changeimageto.com/blog/image-validation-for-machine-learning-datasets.html)
- [Python image quality check guide](https://www.changeimageto.com/blog/python-image-quality-check.html)
- [Automate image quality checks in CI/CD](https://www.changeimageto.com/blog/automate-image-quality-checks-cicd.html)

---

## License

MIT
