A modular Java framework for No-Reference Image Quality Assessment (NR-IQA) with ONNX Runtime inference. Supports 7 state-of-the-art blind IQA models. Includes an ODPS/MaxCompute UDTF adapter for large-scale batch processing.
| Model | Paper | Preprocessing | Crops | Score Range |
|---|---|---|---|---|
| LIQE | CVPR 2023 | CLIP norm, 15 patches | 15 | 1.0 - 5.0 |
| DBCNN | IEEE TCSVT 2020 | ImageNet norm, full image | 1 | continuous |
| HyperIQA | CVPR 2020 | ImageNet norm | 25 | continuous |
| MANIQA | CVPRW 2022 | Inception norm (0.5) | 20 | continuous |
| MUSIQ | ICCV 2021 | [-1, 1] norm | 1 | continuous |
| TReS | WACV 2022 | ImageNet norm | 50 | continuous |
| CLIPIQA | AAAI 2023 | CLIP norm | 1 | 0.0 - 1.0 |
All models are converted from IQA-PyTorch (pyiqa) to ONNX format for Java inference. Pre-converted ONNX weights are available at 86Cao/IQA-ONNX-Models on HuggingFace.
- Architecture
- Project Structure
- Prerequisites
- Quick Start
- Model Conversion
- Building
- Testing
- ODPS Deployment
- Usage Examples
- Adding New Models
- Troubleshooting
- License
┌─────────────────────────┐
│ ImageQualityUDTF │
│ (ODPS entry point) │
└───────────┬─────────────┘
│
┌───────────▼─────────────┐
│ ModelFactory │
│ (creates by name) │
└───────────┬─────────────┘
│
┌───────────▼─────────────┐
│ ModelRegistry │
│ (name → class map) │
└───────────┬─────────────┘
│
┌───────┬───────┬───────┼───────┬───────┬───────┐
▼ ▼ ▼ ▼ ▼ ▼ ▼
LIQE DBCNN HyperIQA MANIQA MUSIQ TReS CLIPIQA
│ │ │ │ │ │ │
└───────┴───────┴───────┼───────┴───────┴───────┘
│
┌───────────▼─────────────┐
│ BaseIQAModel │
│ + BaseONNXManager │
└───────────┬─────────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
ImageDownloader ImagePreprocessor ONNX Runtime
Each model follows the same pattern:
XxxModel.javaextendsBaseIQAModel— handles preprocessing and multi-crop averagingXxxModelManager.javaextendsBaseONNXModelManager— manages ONNX session lifecycle
├── src/main/java/com/autonavi/iqa/
│ ├── common/ # Interfaces and shared types
│ │ ├── IImageQualityModel.java # Model interface
│ │ ├── IModelManager.java # ONNX manager interface
│ │ ├── ModelConfig.java # Configuration POJO
│ │ ├── ModelException.java # Domain exception
│ │ └── QualityScore.java # Score result wrapper
│ ├── models/
│ │ ├── base/
│ │ │ ├── BaseIQAModel.java # Abstract base for all models
│ │ │ └── BaseONNXModelManager.java # ONNX session management
│ │ ├── liqe/ # LIQE implementation
│ │ ├── dbcnn/ # DBCNN implementation
│ │ ├── hyperiqa/ # HyperIQA implementation
│ │ ├── maniqa/ # MANIQA implementation
│ │ ├── musiq/ # MUSIQ implementation
│ │ ├── tres/ # TReS implementation
│ │ └── clipiqa/ # CLIPIQA implementation
│ ├── factory/
│ │ ├── ModelFactory.java # Creates model by name
│ │ └── ModelRegistry.java # Static model registry
│ ├── udtf/
│ │ └── ImageQualityUDTF.java # ODPS UDTF entry point
│ └── utils/
│ ├── ImageDownloader.java # HTTP image fetcher
│ ├── ImagePreprocessor.java # Resize, crop, normalize
│ └── TextFeatureLoader.java # JSON text features (LIQE)
├── src/test/java/com/autonavi/iqa/ # Unit tests (JUnit 5)
├── scripts/
│ ├── liqe_torch2onnx.py # LIQE conversion
│ ├── dbcnn_torch2onnx.py # DBCNN conversion
│ ├── hyperiqa_torch2onnx.py # HyperIQA conversion
│ ├── maniqa_torch2onnx.py # MANIQA conversion
│ ├── musiq_torch2onnx.py # MUSIQ conversion
│ ├── tres_torch2onnx.py # TReS conversion
│ └── clipiqa_torch2onnx.py # CLIPIQA conversion
├── pom.xml
└── README.md
- Python 3.7+
- PyTorch 1.8+
- IQA-PyTorch cloned locally
- onnx, onnxruntime
- JDK 8+ (Java 8 for ODPS compatibility)
- Maven 3.6+
- Alibaba Cloud MaxCompute account
- ODPS CLI configured
git clone https://github.com/86MaxCao/IQA-Java.git
cd IQA-JavaEach model has a dedicated conversion script. Example for LIQE:
python scripts/liqe_torch2onnx.py \
--liqe_model_path /path/to/liqe_mix.pt \
--clip_model_path /path/to/ViT-B-32.pt \
--text_feat_path /path/to/liqe_text_feat_mix.pt \
--output_dir weights/onnxFor other models, conversion scripts load pretrained weights via pyiqa:
# Example: DBCNN
python scripts/dbcnn_torch2onnx.py
# Example: HyperIQA
python scripts/hyperiqa_torch2onnx.pyAll scripts save ONNX files and verify them with onnxruntime before exiting.
mvn clean packageSee ODPS Deployment below.
Each conversion script wraps the PyTorch model to simplify the ONNX graph (eval-mode only, no data augmentation) and exports with:
opset_version=14dynamic_axesfor batch dimensiondo_constant_folding=True
| Model | Script | Input Shape | ONNX Files | Notes |
|---|---|---|---|---|
| LIQE | liqe_torch2onnx.py |
(1,3,224,224) | clip_model.onnx liqe_model.onnx text_features.json |
Requires separate CLIP + LIQE weights, exports text features as JSON |
| DBCNN | dbcnn_torch2onnx.py |
(1,3,512,384) | dbcnn_model.onnx |
Wraps VGG16 + SCNN + bilinear pooling |
| HyperIQA | hyperiqa_torch2onnx.py |
(1,3,224,224) | hyperiqa_model.onnx |
Exports forward_patch only (no multi-crop logic) |
| MANIQA | maniqa_torch2onnx.py |
(1,3,224,224) | maniqa_model.onnx |
Replaces ViT hooks with explicit layer indexing |
| MUSIQ | musiq_torch2onnx.py |
(1,3,224,224) | musiq_model.onnx |
Simplifies multi-scale to single-scale fixed-size |
| TReS | tres_torch2onnx.py |
(1,3,224,224) | tres_model.onnx |
Eval path only (no flipped image / consistency loss) |
| CLIPIQA | clipiqa_torch2onnx.py |
(1,3,224,224) | clipiqa_model.onnx |
Pre-encodes text features as buffer, exports image encoder + scoring head |
The conversion scripts save ONNX files to the output directory you specify. For ODPS deployment, upload them as resources. For local testing, configure paths via ModelConfig:
ModelConfig config = new ModelConfig("liqe");
config.setModelPath("clip_onnx", "/path/to/clip_model.onnx");
config.setModelPath("liqe_onnx", "/path/to/liqe_model.onnx");
config.setModelPath("text_features", "/path/to/text_features.json");# Compile and run tests
mvn clean verify
# Package fat JAR for ODPS (includes all dependencies)
mvn clean packageOutput:
target/iqa-udtf-1.0.0.jar— main JARtarget/iqa-udtf-1.0.0-jar-with-dependencies.jar— fat JAR for ODPS deployment
The fat JAR includes ONNX Runtime, Jackson, JavaCV (with Linux native libraries), and Apache HttpClient.
Unit tests cover core components without requiring ONNX model files or native libraries:
mvn testTest classes:
QualityScoreTest— score wrapper, error handling, constantsModelConfigTest— configuration POJO, typed parameter retrievalModelRegistryTest— model registration, case-insensitive lookup, validationModelFactoryTest— factory creation, error messagesImagePreprocessorTest— normalization, patch selection, ONNX input formatting
-- Upload fat JAR
ADD JAR iqa-udtf-1.0.0-jar-with-dependencies.jar;
-- Upload model files (example for LIQE)
ADD FILE clip_model.onnx;
ADD FILE liqe_model.onnx;
ADD FILE text_features.json;CREATE FUNCTION image_quality AS 'com.autonavi.iqa.udtf.ImageQualityUDTF'
USING 'iqa-udtf-1.0.0-jar-with-dependencies.jar,clip_model.onnx,liqe_model.onnx,text_features.json';SELECT T.url, T.score
FROM (
SELECT COLLECT_LIST(image_url) AS urls
FROM image_table
WHERE dt = '20260601'
) t1
LATERAL VIEW image_quality('liqe', urls) T AS url, score;The first argument selects the model: liqe, dbcnn, hyperiqa, maniqa, musiq, tres, or clipiqa.
SELECT url, score,
CASE
WHEN score < 2.0 THEN 'low'
WHEN score < 3.5 THEN 'medium'
ELSE 'high'
END AS quality_level
FROM (
SELECT COLLECT_LIST(oss_url) AS urls
FROM image_uploads
WHERE dt = '20260601'
GROUP BY batch_id
) t
LATERAL VIEW image_quality('liqe', urls) T AS url, score
WHERE score >= 0; -- exclude errors (score = -1.0)-- Run two models on the same images
SELECT a.url, a.score AS liqe_score, b.score AS dbcnn_score
FROM (
SELECT COLLECT_LIST(image_url) AS urls FROM sample_images
) t
LATERAL VIEW image_quality('liqe', urls) a AS url, score
JOIN (
SELECT url, score FROM (
SELECT COLLECT_LIST(image_url) AS urls FROM sample_images
) t2
LATERAL VIEW image_quality('dbcnn', urls) b AS url, score
) b ON a.url = b.url;SELECT
COUNT(*) AS total,
AVG(score) AS avg_score,
MIN(score) AS min_score,
MAX(score) AS max_score,
SUM(CASE WHEN score >= 3.0 THEN 1 ELSE 0 END) AS high_quality
FROM (
SELECT COLLECT_LIST(image_url) AS urls
FROM image_table
) t
LATERAL VIEW image_quality('liqe', urls) T AS url, score
WHERE score >= 0;-
Create model classes in
src/main/java/com/autonavi/iqa/models/yourmodel/:YourModel.javaextendingBaseIQAModelYourModelManager.javaextendingBaseONNXModelManager
-
Register in
ModelRegistry.java:registerModel("yourmodel", YourModel.class);
-
Create conversion script in
scripts/yourmodel_torch2onnx.py -
Build and test:
mvn clean verify
The factory and UDTF will automatically pick up the new model by name.
Ensure the fat JAR includes Linux native libraries. The javacv-platform dependency bundles them automatically via Maven.
Verify resources are uploaded:
LIST RESOURCES;The project targets Java 8. Verify in pom.xml:
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>The UDTF returns -1.0 for failed downloads and continues processing remaining images. Check ODPS logs for details:
SET odps.udf.log.level=DEBUG;MIT License. See LICENSE.
All models are adapted from open-source implementations:
- LIQE — MIT
- IQA-PyTorch — MIT (DBCNN, HyperIQA, MANIQA, MUSIQ, TReS, CLIPIQA)
- OpenAI CLIP — MIT
- IQA-PyTorch (pyiqa) — Unified IQA toolkit
- LIQE — Vision-language IQA
- ONNX Runtime — Inference engine
- JavaCV — Java OpenCV bindings
- Alibaba Cloud MaxCompute — ODPS platform
@software{iqa_java,
title={IQA-Java: Multi-Model Image Quality Assessment with ONNX Runtime},
url={https://github.com/86MaxCao/IQA-Java},
year={2024}
}