How our solution addresses the problem statement
Detecting AI-generated images is not hard on clean data. A linear classifier on off-the-shelf features reaches 98% AUC on a standard benchmark. But a platform never sees clean data. By the time an image reaches a feed it has been compressed, cropped, screenshotted and re-uploaded, often several times over. On our own baseline, a single transform (downscaling to a quarter size, exactly what a thumbnail generator does) dropped accuracy to 55%. On a two-class problem, that is a coin flip.
The problem statement asks for detection that holds up under realistic post-processing and redistribution. We address it in two ways.
Platform redistribution simulator: Standard augmentation applies one transform at a time. Real images accumulate damage in sequence: resized by a CDN, cropped for a thumbnail, re-encoded on upload, screenshotted. So we train on chains. Each image gets four degraded copies, built by applying one to three operations in random order at the severities listed in the problem statement, plus a screenshot pipeline we added because it is the most common redistribution path on mobile. Order matters: resize-then-JPEG leaves different residue than JPEG-then-resize, because the second operation's artifacts land on top of the first's.
Robustness passport: A detector that is confidently wrong is worse than one that is uncertain, because a platform cannot tell the difference at action time. At inference we score each image five times, using the original plus compressed, blurred, downscaled and noisy versions, then return the mean as the prediction and the spread as a stability score. Answers that agree are safe to auto-action; answers that scatter belong with a human. All five views batch into one forward pass, so the confidence signal is essentially free.
One perturbation module does all three jobs: building training views, building the graded evaluation conditions, and letting the model check its own answer.
Results: Both models are identical, using the same frozen backbone, the same linear classifier and the same 10,000 source images. The only difference is whether the training set included degraded copies. Evaluated on 1,500 held-out images across 15 conditions.
Training on chained degradations raised robust AUC from 0.9330 to 0.9582, a gain of 0.025, at a clean-AUC cost of 0.002 (0.9811 down to 0.9791). Under the challenge formula, half clean and half robust, that nets to a FINAL score of 0.9686 against the baseline's 0.9570.
The effect is largest exactly where the baseline was failing. Worst-case accuracy, at 0.25x resize, rose from 0.5480 to 0.8147. Accuracy spread across all 15 conditions fell from 0.39 to 0.11, so the model now behaves consistently regardless of what happened to the image on its way to us.
On the passport, the 5-view mean scores 0.9853 against 0.9785 for a single prediction, and 94% of all errors fall in the least-stable half of predictions, leaving an auto-actionable half that runs at 99.2% accuracy.
Development tools used
Google Colab (Tesla T4 GPU) for training and evaluation, Jupyter for the exploratory workflow, GitHub for version control, and Windows PowerShell for verifying that the inference script runs on a clean machine outside the notebook environment.
Models or APIs used
DINOv2 ViT-B/14 (Meta, 86M parameters, Apache 2.0), frozen and used purely as a feature extractor. Well under the 2B parameter limit.
scikit-learn LogisticRegression, a 769-parameter linear probe on the frozen 768-dimensional embeddings.
No pretrained AIGC detectors and no external APIs were used. The backbone is never fine-tuned, so any robustness gain is attributable to the training data rather than to added model capacity.
Libraries and frameworks used
PyTorch and torchvision for the backbone, data loading and tensor transforms. scikit-learn for the classifier and all metrics. NumPy for the embedding cache. pandas for results tables. Pillow for every image degradation operation. joblib for model serialisation. matplotlib for the error-analysis figures. kagglehub for dataset download.
Datasets and assets used
CIFAKE, 120,000 images at 32x32 pixels, pairing CIFAR-10 real photographs against diffusion-generated equivalents. Public and MIT-licensed. We use a 10,000 / 1,500 train/test subsample.
All degraded image variants are generated by our own src/transforms.py, which is included in the repository so every result can be reproduced. No proprietary data, no external assets, and no third-party media appear in our submission or demo video.
Built With
- ai
Log in or sign up for Devpost to join the conversation.