StegaQR
StegaQR embeds a small private payload inside a QR code while preserving the public payload for ordinary QR readers. A trained neural decoder recovers the private data.
The package includes a trained hybrid model, repetition and Hamming error correction, a command line interface, and a Python API. The bundled model carries 100 coded bits. With the default repetition code, it carries up to 4 hidden bytes.
Install
pip install stegaQR
StegaQR supports Python 3.10 through 3.12. PyTorch is installed as a required
dependency. Public QR decoding uses pyzbar. Some Linux and macOS environments also
need the native ZBar library supplied by the operating system.
Command line
Inspect the bundled model:
stegaqr info
Create a QR code with a public URL and a private four byte identifier:
stegaqr encode --public "https://example.com/p" --message "ID42" --out stego.png
Recover both payloads:
stegaqr decode --image stego.png
The generated image includes a quiet zone and nearest neighbor upscaling for reliable
scanning. Use --model PATH to select a different trained checkpoint.
Since 0.2.0 the coded bits are spread over the bit grid by a fixed permutation
(--placement interleaved, the default). Images produced with 0.1.0 placed coded bit
c on grid cell c; decode them with --placement native. Encoder and decoder must
use the same placement.
Python API
from stegaqr import decode_hidden, encode_hidden
image = encode_hidden("https://example.com", b"ID42", device="cpu")
public, hidden, metadata = decode_hidden(image, device="cpu")
assert public == "https://example.com"
assert hidden.rstrip(b"\x00") == b"ID42"
CUDA is used when requested and available. Otherwise the package falls back to CPU.
Both functions accept placement="interleaved" (default) or placement="native"
(0.1.0 layout), and placement_seed for the interleaved permutation.
Placement of the error-correction copies
The repetition code tiles its copies, so copy r of message bit j is coded bit
r*k + j. With the 0.1.0 native placement on the bundled model's grid, all copies of
a message bit under Repetition-5 shared one grid column and failed together under
distortion. scripts/eval_ecc_layout.py measures both placements on the same
checkpoints, covers, messages, and distortion draws; on five cross-channel models and
1,024 messages each, interleaving removed every repetition-code message failure. See
experiments/ecc_layout/RESULTS.md.
Embedding modes
The research implementation supports three trained architectures:
| Mode | Design | Purpose |
|---|---|---|
| Segregated | One encoder and decoder per color channel | Channel fault isolation |
| Cross-channel | Joint RGB encoder and decoder | Flexible signal placement |
| Hybrid | Joint RGB model with a QR structure mask | Protects finder and control modules |
The bundled model uses the hybrid architecture with a mask-aware spatial bit grid and no color calibration branch.
Reported results
The saved experiment matrix contains five seed comparisons for the three modes, capacity studies from 25 to 200 coded bits, error correction comparisons, an architecture ablation, and a classical baseline. The physical pilot recovered the public and private payloads from all 10 screen to phone photographs after QR detection and perspective rectification.
The robust operating point has a visible color tint. It should be described as robust data embedding, not invisible steganography. The high PSNR operating point is visually subtle but was not validated for physical capture.
See experiments/full/RESULTS.md,
LOGBOOK.md, and paper/main.pdf for the recorded
evidence and limitations.
Development
git clone https://github.com/jemsbhai/stegaQR.git
cd stegaQR
pip install -e ".[dev,analysis]"
pytest
Train and evaluate a checkpoint:
python scripts/train.py --mode hybrid --mask-aware --no-calibration `
--output-dir experiments/run1
python scripts/evaluate.py --checkpoint experiments/run1/best_model.pt
python scripts/evaluate_real.py --checkpoint experiments/run1/best_model.pt
The complete experiment matrix is resumable:
python scripts/run_experiments.py
python scripts/aggregate_results.py
python scripts/generate_figures.py
License
MIT
Release files for stegaQR 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| stegaqr-0.2.0.tar.gz | 2.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| stegaqr-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.7 MB
Release files / stegaqr-0.2.0.tar.gz
| Download URL | stegaqr-0.2.0.tar.gz |
|---|---|
| Size | 2.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
531eb8a2697d8f9a16b62121e7c781fef9fbd63bbac29d368bd6f4ae27c12209
|
|
BLAKE2b-256 checksum How to use checksums |
845dc18842e78b98260d91631809e6781a5e33516ddb4175d9357c6c160ab1df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / stegaqr-0.2.0-py3-none-any.whl
| Download URL | stegaqr-0.2.0-py3-none-any.whl |
|---|---|
| Size | 2.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0578dac5aefe71e46b1d6d1be143b1dabba464d8cf923f1fea3984b1e856419
|
|
BLAKE2b-256 checksum How to use checksums |
bae9103ccd0543e5154b6afe6062132689d11967a73f2c5b12081541fc0500ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|