Skip to content

About

Implementation of SPAI() and MFM () for the domain of artworks in AI-Generated image detection.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

Repository files navigation

ArtUnmasked

Artist Attribution for Artwork via Compositional Tag Signatures and Deep Embedding Matching

This repository accompanies a research paper currently under peer review. Code and data are provided for reproducibility purposes under the Apache License 2.0.


Overview

ArtUnmasked is a multi-stage artist attribution pipeline for fine-art images. Given an unknown artwork, the system identifies the most likely artist by combining:

  1. AI/Real Detection (SPAI) — Screens out AI-generated images using spectral learning on a ViT-Tiny backbone before attribution begins.
  2. TagMatch — Encodes each artist's style as a sparse composition signature over aspect–concept tag combinations. A rarity-weighted cosine score ranks candidate artists at scale.
  3. DINO + CLIP Nearest-Neighbour Matching — Verifies the top candidates with high-dimensional visual embeddings (DINOv3 + CLIP), using patch-level comparison for fine-grained attribution.
  4. Heatmap Visualisation — Produces interpretable patch-similarity heatmaps to show which regions of the query image most resemble the attributed artist's body of work.

The system is evaluated on a WikiArt-derived dataset spanning thousands of artists across imitation, real-overlap, and diffusion-generated image categories.


Pipeline Architecture

Query Image
     │
     ▼
┌─────────────────────────────────────────┐
│  Stage 1: AI / Real Screening (SPAI)    │
│  ViT-Tiny · Spectral Learning           │
│  → discard AI-generated images          │
└────────────────────┬────────────────────┘
                     │ real artwork only
                     ▼
┌─────────────────────────────────────────┐
│  Stage 2: TagMatch Attribution          │
│  CLIP text embeddings · concept vocab   │
│  Aspect–concept cosine similarity       │
│  Rarity-weighted composition signatures │
│  → Top-K artist candidates              │
└────────────────────┬────────────────────┘
                     │ candidate list
                     ▼
┌─────────────────────────────────────────┐
│  Stage 3: DINO + CLIP Verification      │
│  DINOv3 (vit_small_plus_patch16)        │
│  CLIP (ViT-H-14 / ViT-B-16 / ViT-L-14) │
│  Global CLS + patch-level cosine sim    │
│  → Ranked attribution result            │
└────────────────────┬────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────┐
│  Stage 4: Heatmap Visualisation         │
│  7×7 pooled patch embeddings            │
│  → Interpretable similarity overlay     │
└─────────────────────────────────────────┘

Key Results

Stage Metric Score
TagMatch Top-5 —
TagMatch Top-10 98.6%
DINO + CLIP Top-5 —
DINO + CLIP Top-10 —

Full per-class results are reported in the paper. Ablation results across CLIP backbones are in ablation_outputs/.


Requirements

Python: 3.10+

Core dependencies:

Package Purpose
torch Deep learning backbone
timm DINOv3 model hub
open_clip_torch CLIP text/image encoders
safetensors Efficient tensor serialisation
pandas, numpy Data manipulation
scikit-learn Evaluation metrics
Pillow, opencv-python Image loading and repair
albumentations Image augmentation
yacs Hierarchical configuration
tqdm Progress reporting
matplotlib Visualisation

Install all dependencies into a virtual environment:

python -m venv .venv
source .venv/bin/activate
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
pip install timm open_clip_torch safetensors pandas numpy scikit-learn \
            Pillow opencv-python albumentations yacs tqdm matplotlib

A GPU is strongly recommended. CPU fallback is supported but timings will be significantly higher.


Project Structure

ArtUnmasked/
├── ArtUnmasked/                          # Core Python package
│   ├── CONFIG.py                         # Centralised YACS config (all file paths & hyperparameters)
│   ├── main.py                           # End-to-end inference entry point
│   ├── utils.py                          # Image validation, repair utilities, CustomTimer
│   │
│   ├── ArtWork_Tagging/                  # TagMatch module
│   │   ├── tag_match.py                  # TagMatch inference engine → (df, top10_acc, top5_acc)
│   │   ├── calculate_artist_signatures.py # Build tensorized artist composition signatures
│   │   ├── compute_cosine_similarity.py  # Tag–image cosine scores (mode="train"/"test")
│   │   ├── compute_clip_text_embeddings.py # Embed concept vocabulary with CLIP
│   │   ├── compute_clip_image_embeddings.py # Embed images with CLIP
│   │   └── Artwork_Vocabulary - Sheet2.csv # Aspect–concept vocabulary (~100 pairs)
│   │
│   ├── dinov3_clip_inference/            # DINO + CLIP matching module
│   │   ├── embedders.py                  # DINOv3Embedder & CLIPEmbedder wrappers
│   │   ├── save_dinov3_clip_embeddings.py # Bulk embedding generation (safetensors)
│   │   ├── dino_v3_clip_inference.py     # Nearest-neighbour attribution
│   │   └── compute_heatmaps.py           # Patch-level similarity heatmaps
│   │
│   ├── ai_vs_real/                       # SPAI integration (AI-generated image detection)
│   │   └── spai/                         # Modified SPAI codebase (see Third-Party section)
│   │
│   ├── analysis/                         # Visualisation and distribution plots
│   └── data/                             # Embeddings, CSVs, and dataset splits
│
├── ablation_runner.py                    # CLIP backbone ablation study (3 variants)
├── run_eval.py                           # Full pipeline evaluation
├── create_eval_dataset.py                # Evaluation dataset construction
├── wikiart/                              # WikiArt data fetching utilities
│
├── ablation_outputs/                     # Ablation results (CSV + LaTeX tables)
├── eval_outputs/                         # Evaluation results
├── Journal_Submission___ArtUnmasked/     # Paper draft and supplementary materials
│
├── NOTICE                                # Third-party attribution (SPAI)
├── LICENSE                               # Apache License 2.0
└── README.md                             # This file

Configuration

All file paths and hyperparameters are centralised in ArtUnmasked/CONFIG.py using YACS. Key config groups:

Group Key Settings
Root paths PROJECT_ROOT, DATA_ROOT, OUTPUT_ROOT, PRETRAINED_ROOT
WikiArt data PD_WIKIART (70k paintings CSV), GLOBAL_WIKIART_DINOV3_CLIP_EMBEDDINGS
Artwork Tagging TEXT_CONCEPT_EMBEDDINGS_NPZ, GLOBAL_COMPOSITIONS, ARTIST_TAGS_COSINE_SIMILARITIES
Test / Eval TEST_ROOT, TEST_DATASET_CLIP_DINO_EMBEDDINGS
Models MODEL.PRETRAINED_SPAI, SPAI_CONFIG_PATH

To override a setting without editing the file, monkey-patch the CfgNode before calling any module function (as ablation_runner.py does via patch_configs()).


Datasets

Dataset Description
WikiArt (Public Domain 70%) ~70,000 artworks across hundreds of artists. Used to build artist signatures and global DINO+CLIP embeddings.
Eval Dataset ~10,500 images across four classes: imitation (~5k), real_overlap (~2.5k), real_new (~2.5k), diffusion (~1k).
DiffusionDB AI-generated images used for SPAI detection evaluation.
Concept Vocabulary ~100 aspect–concept pairs (e.g., landscape__mountains, portrait__gaze) generated with Vicuna-13B and curated manually.

Large binary files (safetensors embeddings, model checkpoints) are excluded from the repository. See the paper supplementary for download instructions.


Usage

End-to-End Inference

cd /home/thesalad/PycharmProjects/ArtUnmasked
python -m ArtUnmasked.main

The pipeline stages are individually toggled inside main.py. By default the full flow runs:

  1. Save test DINO+CLIP embeddings
  2. Run DINO+CLIP nearest-neighbour matching
  3. Compute heatmaps

SPAI screening and TagMatch are available as commented-out blocks and can be enabled as needed.

Running the CLIP Ablation Study

python ablation_runner.py

This sweeps three CLIP backbones (ViT-H-14, ViT-B-16, ViT-L-14) with fixed TagMatch hyperparameters:

  • Train: top_k_tags=25, max_comb_size=3
  • Test: max_tags_per_image=15, max_comp_size=3

Outputs (written to ablation_outputs/):

File Contents
{variant}/ Per-variant embeddings, similarity CSVs, and compositions
ablation_summary.csv Machine-readable Top-5 / Top-10 accuracy + per-step wall-clock times
ablation_tables.txt Plain-text formatted comparison table
ablation_tables.tex LaTeX booktabs table for direct inclusion in the paper

The LaTeX table is included in the paper template via:

\input{../ablation_outputs/ablation_tables}

Steps that hit the cache report 0.0 s in the timing columns. The LaTeX caption notes this explicitly.

Running the Evaluation

python run_eval.py

Evaluates the full pipeline on the eval dataset and reports per-class accuracy metrics, printed to stdout and saved to eval_outputs/.

Building Artist Signatures (one-time setup)

If WikiArt embeddings or composition signatures are not yet generated, run the relevant steps from ArtUnmasked/main.py or call directly:

from ArtUnmasked.ArtWork_Tagging.compute_clip_text_embeddings import embed_concepts
from ArtUnmasked.ArtWork_Tagging.compute_cosine_similarity import compute_cosine_similarity
from ArtUnmasked.ArtWork_Tagging.calculate_artist_signatures import build_artist_signatures

embed_concepts()                          # → concept_embeddings.npz
compute_cosine_similarity(mode="train")   # → artist_tags_cosine_similarities.csv
build_artist_signatures()                 # → global_compositions.safetensors + .json

TagMatch — Algorithm Summary

TagMatch attributes artwork via composition signatures: compact, sparse representations of each artist's recurring stylistic combinations.

Training phase:

  1. Embed the concept vocabulary (e.g., landscape__mountains) using the CLIP text encoder.
  2. For each training image, compute cosine similarities between its CLIP embedding and all concept embeddings; retain concepts with z-score ≥ 1.75.
  3. Form tag combinations of size 2–3 (max_comb_size=3); keep the top-k most distinctive per image.
  4. Aggregate across an artist's training images into a sparse COO tensor (artists × compositions) weighted by per-composition rarity.

Inference phase:

  1. Repeat steps 1–3 on the test image (max_tags_per_image=15).
  2. Score each artist by rarity-weighted cosine similarity between the test composition vector and the artist's signature.
  3. Return a ranked candidate list; report Top-5 and Top-10 accuracy.

The TagMatch function signature is:

df, top10_acc, top5_acc = run_tagmatch_inference(cfg, ...)

Third-Party Components

ArtUnmasked/ai_vs_real/ — Modified SPAI

The ai_vs_real/ directory contains a modified version of SPAI (Any-Resolution AI-Generated Image Detection by Spectral Learning), originally developed by the Centre for Research and Technology Hellas (CERTH) and the University of Amsterdam.

Original repository: https://github.com/mever-team/spai Original licence: Apache License 2.0 Original copyright: © 2025 CERTH and University of Amsterdam

Modifications made for ArtUnmasked (in compliance with the Apache 2.0 licence):

Change Description
Architecture swap ViT-Base backbone replaced with ViT-Tiny pretrained via Masked Feature Modelling (MFM) for reduced compute on artwork classification
Simplified loader Multi-format dataset loaders replaced with a single-CSV test loader
Dependency removal CLI interface, Neptune experiment logging, LMDB storage, ONNX export, and Automatic Mixed Precision (AMP) removed
Integration Training, testing, and inference refactored into callable Python functions for embedding within the ArtUnmasked pipeline
Repository cleanup Unused documentation, training scripts, and example assets removed
Configuration SPAI config system retained and adapted (configs/spai.yaml, spai_config.py)

The modified SPAI code is redistributed under the Apache License 2.0. All modifications are documented in:

  • ArtUnmasked/ai_vs_real/spai/NOTICE — detailed change log attributing modifications to Akshad Vijay Chidrawar (2025)
  • NOTICE (project root) — top-level attribution notice

The full Apache 2.0 licence text is available at ArtUnmasked/ai_vs_real/spai/LICENSE.


License

This project is licensed under the Apache License, Version 2.0.

Copyright 2025 Akshad Vijay Chidrawar

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

See the LICENSE file at the project root for the full licence text.


Reproducibility Notes

  • GPU: A CUDA-capable GPU is required for meaningful wall-clock timings. CPU fallback is available but substantially slower.
  • Memory: The WikiArt patch embeddings file (WIKIART_PATCH_EMBEDDINGS.safetensors) is ~871 MB. DINO+CLIP global embeddings are ~44 MB. Ensure sufficient disk and VRAM (≥ 8 GB recommended).
  • Caching: Expensive steps (concept embedding, cosine similarity, artist signatures) are automatically cached. Re-running will skip cached steps and report 0.0 s in timing outputs.
  • OOM prevention: The ablation runner calls torch.cuda.empty_cache() and deletes the CLIP model between variants.
  • Torch compile: torch.compile() is applied to both DINOv3 and CLIP models; the first forward pass incurs a one-time compilation cost.

Citation

If you use ArtUnmasked or the TagMatch algorithm in your research, please cite our paper:

@article{artunmasked2025,
  title     = {ArtUnmasked: A Multimodal Classifier for Real, AI, and Imitated Artworks},
  author    = {Chidrawar, Akshad Vijay and others},
  journal   = {Under Review},
  year      = {2025}
}

Citation will be updated upon publication.


Acknowledgements

  • SPAI — CERTH and University of Amsterdam for the original spectral AI-detection framework (mever-team/spai)
  • WikiArt — Publicly available artwork metadata used for training and evaluation
  • timm — Ross Wightman and the timm community for the DINOv3 model hub
  • OpenCLIP — LAION for the open-source CLIP training and weights
  • DiffusionDB — Wang et al. for the diffusion-generated image dataset used in SPAI evaluation

About

Implementation of SPAI() and MFM () for the domain of artworks in AI-Generated image detection.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages