Inspiration

QR codes are everywhere now — restaurant menus, payments, event check-ins — but it's very easy to hide a phishing link behind one. You can't tell just by looking at it. I wanted to see if a simple CNN could learn to flag suspicious-looking QR codes from the image alone, and more importantly, whether it would still work once the image is low quality (blurry, rotated, or poorly lit) like a real phone camera scan.

What it does

The app takes a QR code image (uploaded, in bulk, or straight from your camera) and classifies it as Benign or Malicious, along with a confidence score. It also shows a Grad-CAM heatmap of which part of the image the model focused on, so the prediction isn't a black box.

How we built it Trained a small CNN (Conv2D + MaxPooling blocks, Dropout, Dense) on a dataset of 1,000 QR code images (500 benign, 500 malicious) in Google Colab using TensorFlow/Keras. Ran 6 experiments changing one hyperparameter at a time — epochs (10/15/25), conv filter sizes (16-32-64 vs 32-64-128), and dropout (0.3 vs 0.5) — and logged validation accuracy for each. Built a distort() function (rotation, Gaussian blur, brightness shift, noise) to simulate real-world camera conditions, and generated a distorted copy of the full dataset. Evaluated the clean-trained model directly on distorted images (no retraining) to measure the real accuracy drop, then retrained a second model on distorted data to see how much of that gap could be recovered. Deployed the best model as a Streamlit app with single/batch image upload, live camera input, and Grad-CAM visual explanations. Tested the deployed app on QR codes outside the original dataset to sanity-check real-world reliability. Results Model Tested on Accuracy Clean-trained Clean images 87.5% Clean-trained Distorted images 68.0% Distorted-trained Distorted images 81.0% Distorted-trained Clean images 80.5%

A clean-trained model loses about 19.5 points of accuracy on distorted QR images, and training on distorted data recovers about 13 of those points back — at a small cost to clean-image accuracy.

Challenges we ran into Getting the dataset into the right folder structure in Colab (it came zipped inside a RAR file nested inside a zip). A cp -r command silently duplicated a folder on a Colab restart, which briefly turned the dataset into 3 classes instead of 2, and took some debugging to catch. Keeping the model small enough to host for free: GitHub rejects files over 25MB, so the trained .keras model is hosted on Google Drive and downloaded by the app at runtime with gdown. What we learned A model that looks great on clean validation data can fail badly on realistic, slightly-degraded images, and that gap is only visible if you deliberately test for it. Small, deliberate hyperparameter experiments (changing one variable at a time) make it much easier to reason about what actually helped. Grad-CAM is a cheap way to add some interpretability to an otherwise black-box CNN. What's next Train on a larger, more diverse QR dataset. Combine the image-based CNN with actual URL/content analysis of the decoded QR, since the current model only looks at visual patterns. Add more realistic distortions (motion blur, perspective skew, partial occlusion).

Built With

Share this project:

Updates

Submission history