Ankush commited on
Commit ·
078ce08
0
Parent(s):
Initial commit — StegNet
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +10 -0
- .gitignore +1 -0
- README.md +100 -0
- app.py +197 -0
- app/__init__.py +0 -0
- app/main_CLI_v1.py +75 -0
- app/models/DEEP_STEGO/Utils/customLossWeight.py +14 -0
- app/models/DEEP_STEGO/Utils/enhance.py +70 -0
- app/models/DEEP_STEGO/Utils/eval.py +135 -0
- app/models/DEEP_STEGO/Utils/preprocessing.py +18 -0
- app/models/DEEP_STEGO/Utils/progressbarCL_animation.py +7 -0
- app/models/DEEP_STEGO/Utils/test.py +80 -0
- app/models/DEEP_STEGO/checkpoints/steg_model-06-0.03.hdf5 +3 -0
- app/models/DEEP_STEGO/hide_image.py +46 -0
- app/models/DEEP_STEGO/models/hide.h5 +3 -0
- app/models/DEEP_STEGO/models/hide.h5.png +3 -0
- app/models/DEEP_STEGO/models/hide.png +3 -0
- app/models/DEEP_STEGO/models/model_double.png +3 -0
- app/models/DEEP_STEGO/models/reveal.h5 +3 -0
- app/models/DEEP_STEGO/models/reveal.h5.png +3 -0
- app/models/DEEP_STEGO/models/reveal.png +3 -0
- app/models/DEEP_STEGO/results/input.png +3 -0
- app/models/DEEP_STEGO/results/output.png +3 -0
- app/models/DEEP_STEGO/reveal_image.py +45 -0
- app/models/DEEP_STEGO/test/cover.png +3 -0
- app/models/DEEP_STEGO/test/images/100098.jpg +3 -0
- app/models/DEEP_STEGO/test/images/101027.jpg +3 -0
- app/models/DEEP_STEGO/test/images/103006.jpg +3 -0
- app/models/DEEP_STEGO/test/images/103029.jpg +3 -0
- app/models/DEEP_STEGO/test/images/104010.jpg +3 -0
- app/models/DEEP_STEGO/test/images/105027.jpg +3 -0
- app/models/DEEP_STEGO/test/images/106005.jpg +3 -0
- app/models/DEEP_STEGO/test/images/106024.jpg +3 -0
- app/models/DEEP_STEGO/test/images/106025.jpg +3 -0
- app/models/DEEP_STEGO/test/images/106047.jpg +3 -0
- app/models/DEEP_STEGO/test/images/107072.jpg +3 -0
- app/models/DEEP_STEGO/test/images/108004.jpg +3 -0
- app/models/DEEP_STEGO/test/images/108041.jpg +3 -0
- app/models/DEEP_STEGO/test/images/108069.jpg +3 -0
- app/models/DEEP_STEGO/test/images/108070.jpg +3 -0
- app/models/DEEP_STEGO/test/images/112056.jpg +3 -0
- app/models/DEEP_STEGO/test/images/112082.jpg +3 -0
- app/models/DEEP_STEGO/test/images/113016.jpg +3 -0
- app/models/DEEP_STEGO/test/images/113044.jpg +3 -0
- app/models/DEEP_STEGO/test/images/12003.jpg +3 -0
- app/models/DEEP_STEGO/test/images/124084.jpg +3 -0
- app/models/DEEP_STEGO/test/images/126007.jpg +3 -0
- app/models/DEEP_STEGO/test/images/130014.jpg +3 -0
- app/models/DEEP_STEGO/test/images/130026.jpg +3 -0
- app/models/DEEP_STEGO/test/images/134008.jpg +3 -0
.gitattributes
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.hdf5 filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
app/ui/assets/components_backgrounds/main_window_welcome_bg.png filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.ico filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.json filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.idea/
|
README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<h1 align="center">
|
| 2 |
+
InvisiCipher : Deep Learning-Based image Steganography with Chaotic Encryption and
|
| 3 |
+
Enhanced Super Resolution
|
| 4 |
+
</h1>
|
| 5 |
+
|
| 6 |
+
<p align="center">
|
| 7 |
+
<img src="app/ui/logo.png" alt="Project Logo" width="100">
|
| 8 |
+
</p>
|
| 9 |
+
|
| 10 |
+
<p align="center">
|
| 11 |
+
<strong>Hide secrets, enhance images!</strong>
|
| 12 |
+
</p>
|
| 13 |
+
|
| 14 |
+
## Overview
|
| 15 |
+
|
| 16 |
+
Welcome to our Steganography and Super Resolution project! This project combines the power of steganography techniques and super-resolution using deep learning models. Our goal is to hide a secret image within a cover image using advanced convolutional neural networks (CNNs) and then enhance the quality of the hidden image using an Enhanced Super Resolution Generative Adversarial Network (ESRGAN). We also provide an option to encrypt the steg image using various chaos encryption algorithms for added security.
|
| 17 |
+
|
| 18 |
+
## Features
|
| 19 |
+
|
| 20 |
+
✨ **Interactive Hiding**: Utilize our intuitive hide network powered by CNNs to embed secret images within cover images effortlessly.
|
| 21 |
+
|
| 22 |
+
🔒 **Secure Encryption**: Choose from multiple chaos encryption algorithms such as AES, Blowfish to encrypt your steg image and protect your secrets.
|
| 23 |
+
|
| 24 |
+
🌟 **Enhanced Super Resolution**: Witness the magic of our ESRGAN model as it enhances the resolution and quality of the hidden image, revealing every detail.
|
| 25 |
+
|
| 26 |
+
🎨 **Easy-to-Use**: Our project provides a user-friendly interface and simple scripts to perform hiding, encryption, decryption, and image enhancement with just a few lines of code.
|
| 27 |
+
|
| 28 |
+
## Project Architecture
|
| 29 |
+
|
| 30 |
+
The project architecture consists of the following components:
|
| 31 |
+
|
| 32 |
+
1. **Prepare Network**: A CNN-based network that prepares the secret image for hiding by extracting essential features and encoding it.
|
| 33 |
+
|
| 34 |
+
2. **Hide Network**: Another CNN-based network that embeds the prepared secret image within the cover image, producing the steg image.
|
| 35 |
+
|
| 36 |
+
3. **Chaos Encryption**: Choose between AES encryption, Blowfish encryption to secure your steg image.
|
| 37 |
+
|
| 38 |
+
4. **Chaos Decryption**: Decrypt the encrypted steg image using the corresponding decryption algorithm to retrieve the steg image.
|
| 39 |
+
|
| 40 |
+
5. **Reveal Network**: A CNN-based network that extracts the secret image from the steg image by decoding the hidden information.
|
| 41 |
+
|
| 42 |
+
6. **ESRGAN**: Our Enhanced Super Resolution Generative Adversarial Network (ESRGAN) model enhances the quality and resolution of the extracted secret image.
|
| 43 |
+
|
| 44 |
+
## Getting Started
|
| 45 |
+
|
| 46 |
+
To get started with our project, follow these steps:
|
| 47 |
+
|
| 48 |
+
1. **Clone the Repository**: `git clone https://github.com/Asirwad/InvisiCipher.git`
|
| 49 |
+
|
| 50 |
+
2. **Install Dependencies**: Install the required dependencies by running `pip install -r requirements.txt`.
|
| 51 |
+
|
| 52 |
+
3. **Prepare Your Dataset**: Organize your cover and secret images dataset and place them in the appropriate directories.
|
| 53 |
+
|
| 54 |
+
4. **Customize Configuration**: Modify the configuration files to set the desired parameters for the models and encryption algorithms.
|
| 55 |
+
|
| 56 |
+
5. **Train the Models**: Run the training script to train the CNN models and ESRGAN: `python train.py`.
|
| 57 |
+
|
| 58 |
+
6. **Explore the Scripts**: Utilize the provided scripts to hide, encrypt, reveal, and enhance images based on your specific requirements.
|
| 59 |
+
|
| 60 |
+
## Welcome screen
|
| 61 |
+
|
| 62 |
+
<p align="center">
|
| 63 |
+
<img src="app/ui/assets/readme_assets/main_window.png" alt="Welcome" width="1000">
|
| 64 |
+
</p>
|
| 65 |
+
|
| 66 |
+
## Image hide
|
| 67 |
+
|
| 68 |
+
<p align="center">
|
| 69 |
+
<img src="app/ui/assets/readme_assets/hide.png" alt="Image hide" width="1000">
|
| 70 |
+
</p>
|
| 71 |
+
|
| 72 |
+
## Image reveal
|
| 73 |
+
|
| 74 |
+
<p align="center">
|
| 75 |
+
<img src="app/ui/assets/readme_assets/reveal.png" alt="Image reveal" width="1000">
|
| 76 |
+
</p>
|
| 77 |
+
|
| 78 |
+
## Super resolution
|
| 79 |
+
|
| 80 |
+
<p align="center">
|
| 81 |
+
<img src="app/ui/assets/readme_assets/superres.png" alt="Super resolution" width="1000">
|
| 82 |
+
</p>
|
| 83 |
+
|
| 84 |
+
## Contributing
|
| 85 |
+
|
| 86 |
+
We welcome contributions from the open source community. If you find any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request.
|
| 87 |
+
|
| 88 |
+
## Acknowledgements
|
| 89 |
+
|
| 90 |
+
We would like to acknowledge the following resources and libraries used in this project:
|
| 91 |
+
|
| 92 |
+
- <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Tensorflow_logo.svg/1915px-Tensorflow_logo.svg.png" alt="TensorFlow" width="26" align="center"> TensorFlow: [↗️](https://www.tensorflow.org/)
|
| 93 |
+
- <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/PyTorch_logo_icon.svg/1200px-PyTorch_logo_icon.svg.png"
|
| 94 |
+
alt="PyTorch" width="25" align="center"> PyTorch: [↗️](https://pytorch.org/)
|
| 95 |
+
- <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Python_and_Qt.svg/800px-Python_and_Qt.svg.png"
|
| 96 |
+
alt="PyQt" width="25" align="center"> PyQt: [↗️](https://www.qt.io/qt-for-python)
|
| 97 |
+
|
| 98 |
+
## Contact
|
| 99 |
+
|
| 100 |
+
For any questions or inquiries, please contact us at [asirwadsali@gmail.com](mailto:asirwadsali@gmail.com).
|
app.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
StegNet — Gradio web interface.
|
| 3 |
+
|
| 4 |
+
Entry point for HuggingFace Spaces (or any Gradio-compatible host).
|
| 5 |
+
Set the HF_API_KEY environment variable (Spaces secret) to enable
|
| 6 |
+
the "Generate Image" tab.
|
| 7 |
+
|
| 8 |
+
Run locally:
|
| 9 |
+
python app.py
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import os
|
| 13 |
+
import sys
|
| 14 |
+
|
| 15 |
+
# Make sure the package root is on the path when run directly
|
| 16 |
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 17 |
+
|
| 18 |
+
import gradio as gr
|
| 19 |
+
|
| 20 |
+
from app.models.DEEP_STEGO.hide_image import hide_image
|
| 21 |
+
from app.models.DEEP_STEGO.reveal_image import reveal_image
|
| 22 |
+
from app.models.ESRGAN.upscale_image import upscale_image
|
| 23 |
+
from app.models.encryption import aes, blowfish
|
| 24 |
+
from app.models.StableDiffusionAPI.StableDiffusionV2 import generate
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# ---------------------------------------------------------------------------
|
| 28 |
+
# Handler functions
|
| 29 |
+
# ---------------------------------------------------------------------------
|
| 30 |
+
|
| 31 |
+
def hide_fn(cover, secret):
|
| 32 |
+
if cover is None or secret is None:
|
| 33 |
+
return None, "Please upload both a cover image and a secret image."
|
| 34 |
+
try:
|
| 35 |
+
output_path = hide_image(cover, secret)
|
| 36 |
+
return output_path, "Secret image hidden successfully!"
|
| 37 |
+
except Exception as e:
|
| 38 |
+
return None, f"Error: {e}"
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def reveal_fn(steg):
|
| 42 |
+
if steg is None:
|
| 43 |
+
return None, "Please upload a steg image."
|
| 44 |
+
try:
|
| 45 |
+
output_path = reveal_image(steg)
|
| 46 |
+
return output_path, "Secret image revealed successfully!"
|
| 47 |
+
except Exception as e:
|
| 48 |
+
return None, f"Error: {e}"
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def encrypt_fn(image, key, algo):
|
| 52 |
+
if image is None:
|
| 53 |
+
return None, "Please upload an image."
|
| 54 |
+
if not key:
|
| 55 |
+
return None, "Please enter a secret key."
|
| 56 |
+
try:
|
| 57 |
+
if algo == "AES":
|
| 58 |
+
aes.encrypt(image, key)
|
| 59 |
+
else:
|
| 60 |
+
blowfish.encrypt(image, key)
|
| 61 |
+
enc_path = image + ".enc"
|
| 62 |
+
return enc_path, f"Image encrypted with {algo}. Download the file below."
|
| 63 |
+
except Exception as e:
|
| 64 |
+
return None, f"Error: {e}"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def decrypt_fn(enc_file, key, algo):
|
| 68 |
+
if enc_file is None:
|
| 69 |
+
return None, "Please upload an encrypted .enc file."
|
| 70 |
+
if not key:
|
| 71 |
+
return None, "Please enter the secret key."
|
| 72 |
+
try:
|
| 73 |
+
if algo == "AES":
|
| 74 |
+
code, filename = aes.decrypt(enc_file, key)
|
| 75 |
+
else:
|
| 76 |
+
code, filename = blowfish.decrypt(enc_file, key)
|
| 77 |
+
if code == -1:
|
| 78 |
+
return None, "Decryption failed — wrong key."
|
| 79 |
+
return filename, "Image decrypted successfully!"
|
| 80 |
+
except Exception as e:
|
| 81 |
+
return None, f"Error: {e}"
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def upscale_fn(image):
|
| 85 |
+
if image is None:
|
| 86 |
+
return None, "Please upload a low-resolution image."
|
| 87 |
+
try:
|
| 88 |
+
output_path = upscale_image(image)
|
| 89 |
+
return output_path, "Image upscaled 4× successfully!"
|
| 90 |
+
except Exception as e:
|
| 91 |
+
return None, f"Error: {e}"
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def generate_fn(prompt):
|
| 95 |
+
if not prompt or not prompt.strip():
|
| 96 |
+
return None, "Please enter a text prompt."
|
| 97 |
+
if not os.environ.get("HF_API_KEY"):
|
| 98 |
+
return None, "HF_API_KEY is not set. Add it as a Space secret to enable image generation."
|
| 99 |
+
try:
|
| 100 |
+
img = generate(prompt.strip())
|
| 101 |
+
return img, "Image generated successfully!"
|
| 102 |
+
except Exception as e:
|
| 103 |
+
return None, f"Error: {e}"
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
# ---------------------------------------------------------------------------
|
| 107 |
+
# Gradio UI
|
| 108 |
+
# ---------------------------------------------------------------------------
|
| 109 |
+
|
| 110 |
+
DESCRIPTION = """
|
| 111 |
+
# StegNet
|
| 112 |
+
### AI-Based Secure Image Steganography Platform
|
| 113 |
+
|
| 114 |
+
Hide secret images inside cover images using deep learning, encrypt the result,
|
| 115 |
+
reveal hidden images, enhance resolution with ESRGAN, or generate new images
|
| 116 |
+
with Stable Diffusion — all in one place.
|
| 117 |
+
"""
|
| 118 |
+
|
| 119 |
+
with gr.Blocks(title="StegNet", theme=gr.themes.Soft()) as demo:
|
| 120 |
+
gr.Markdown(DESCRIPTION)
|
| 121 |
+
|
| 122 |
+
# ── Tab 1: Hide Image ──────────────────────────────────────────────────
|
| 123 |
+
with gr.Tab("🔒 Hide Image"):
|
| 124 |
+
gr.Markdown("Upload a **cover image** and a **secret image**. The model embeds the secret inside the cover.")
|
| 125 |
+
with gr.Row():
|
| 126 |
+
cover_input = gr.Image(type="filepath", label="Cover Image")
|
| 127 |
+
secret_input = gr.Image(type="filepath", label="Secret Image")
|
| 128 |
+
hide_btn = gr.Button("Hide Secret", variant="primary")
|
| 129 |
+
with gr.Row():
|
| 130 |
+
steg_output = gr.Image(label="Steg Image (download me)")
|
| 131 |
+
hide_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 132 |
+
hide_btn.click(hide_fn, inputs=[cover_input, secret_input], outputs=[steg_output, hide_status])
|
| 133 |
+
|
| 134 |
+
# ── Tab 2: Reveal Image ────────────────────────────────────────────────
|
| 135 |
+
with gr.Tab("🔍 Reveal Image"):
|
| 136 |
+
gr.Markdown("Upload a **steg image** to extract the hidden secret image.")
|
| 137 |
+
steg_input = gr.Image(type="filepath", label="Steg Image")
|
| 138 |
+
reveal_btn = gr.Button("Reveal Secret", variant="primary")
|
| 139 |
+
with gr.Row():
|
| 140 |
+
revealed_output = gr.Image(label="Revealed Secret Image")
|
| 141 |
+
reveal_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 142 |
+
reveal_btn.click(reveal_fn, inputs=[steg_input], outputs=[revealed_output, reveal_status])
|
| 143 |
+
|
| 144 |
+
# ── Tab 3: Encrypt Image ───────────────────────────────────────────────
|
| 145 |
+
with gr.Tab("🛡️ Encrypt Image"):
|
| 146 |
+
gr.Markdown("Encrypt any image file (e.g. your steg image) with AES or Blowfish.")
|
| 147 |
+
enc_image_input = gr.Image(type="filepath", label="Image to Encrypt")
|
| 148 |
+
with gr.Row():
|
| 149 |
+
enc_key_input = gr.Textbox(label="Secret Key", type="password", placeholder="Enter a strong key…")
|
| 150 |
+
enc_algo = gr.Radio(["AES", "Blowfish"], value="AES", label="Algorithm")
|
| 151 |
+
enc_btn = gr.Button("Encrypt", variant="primary")
|
| 152 |
+
with gr.Row():
|
| 153 |
+
enc_file_output = gr.File(label="Encrypted File (.enc) — Download")
|
| 154 |
+
enc_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 155 |
+
enc_btn.click(encrypt_fn, inputs=[enc_image_input, enc_key_input, enc_algo], outputs=[enc_file_output, enc_status])
|
| 156 |
+
|
| 157 |
+
# ── Tab 4: Decrypt Image ───────────────────────────────────────────────
|
| 158 |
+
with gr.Tab("🔓 Decrypt Image"):
|
| 159 |
+
gr.Markdown("Upload an encrypted **.enc** file and the correct key to recover the image.")
|
| 160 |
+
dec_file_input = gr.File(label="Encrypted File (.enc)", type="filepath")
|
| 161 |
+
with gr.Row():
|
| 162 |
+
dec_key_input = gr.Textbox(label="Secret Key", type="password", placeholder="Enter the key used for encryption…")
|
| 163 |
+
dec_algo = gr.Radio(["AES", "Blowfish"], value="AES", label="Algorithm")
|
| 164 |
+
dec_btn = gr.Button("Decrypt", variant="primary")
|
| 165 |
+
with gr.Row():
|
| 166 |
+
dec_image_output = gr.Image(label="Decrypted Image")
|
| 167 |
+
dec_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 168 |
+
dec_btn.click(decrypt_fn, inputs=[dec_file_input, dec_key_input, dec_algo], outputs=[dec_image_output, dec_status])
|
| 169 |
+
|
| 170 |
+
# ── Tab 5: Super Resolution ────────────────────────────────────────────
|
| 171 |
+
with gr.Tab("✨ Super Resolution"):
|
| 172 |
+
gr.Markdown("Upscale any image **4×** using ESRGAN.")
|
| 173 |
+
lr_input = gr.Image(type="filepath", label="Low-Resolution Image")
|
| 174 |
+
upscale_btn = gr.Button("Upscale 4×", variant="primary")
|
| 175 |
+
with gr.Row():
|
| 176 |
+
hr_output = gr.Image(label="High-Resolution Output")
|
| 177 |
+
upscale_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 178 |
+
upscale_btn.click(upscale_fn, inputs=[lr_input], outputs=[hr_output, upscale_status])
|
| 179 |
+
|
| 180 |
+
# ── Tab 6: Generate Image ──────────────────────────────────────────────
|
| 181 |
+
with gr.Tab("🎨 Generate Image"):
|
| 182 |
+
gr.Markdown(
|
| 183 |
+
"Generate an image from a text prompt using Stable Diffusion 2.1. \n"
|
| 184 |
+
"*(Requires `HF_API_KEY` set as a Space secret.)*"
|
| 185 |
+
)
|
| 186 |
+
prompt_input = gr.Textbox(
|
| 187 |
+
label="Text Prompt",
|
| 188 |
+
placeholder="A futuristic city at sunset, digital art…",
|
| 189 |
+
lines=2,
|
| 190 |
+
)
|
| 191 |
+
gen_btn = gr.Button("Generate", variant="primary")
|
| 192 |
+
with gr.Row():
|
| 193 |
+
gen_output = gr.Image(label="Generated Image")
|
| 194 |
+
gen_status = gr.Textbox(label="Status", interactive=False, lines=2)
|
| 195 |
+
gen_btn.click(generate_fn, inputs=[prompt_input], outputs=[gen_output, gen_status])
|
| 196 |
+
|
| 197 |
+
demo.launch()
|
app/__init__.py
ADDED
|
File without changes
|
app/main_CLI_v1.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tkinter import filedialog
|
| 2 |
+
|
| 3 |
+
from app.models.encryption import blowfish
|
| 4 |
+
from app.models.DEEP_STEGO.hide_image import hide_image
|
| 5 |
+
from app.models.DEEP_STEGO.reveal_image import reveal_image
|
| 6 |
+
from app.models.ESRGAN.upscale_image import upscale_image
|
| 7 |
+
from app.models.encryption import aes as aes_chaos
|
| 8 |
+
|
| 9 |
+
print("StegNet CLI")
|
| 10 |
+
|
| 11 |
+
""" DEEP STEGANO """
|
| 12 |
+
print("Image hiding")
|
| 13 |
+
print("input the cover image filename")
|
| 14 |
+
cover_filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 15 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 16 |
+
print("input the secret image filename")
|
| 17 |
+
secret_filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 18 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 19 |
+
hide_image(cover_filename, secret_filename)
|
| 20 |
+
|
| 21 |
+
print("image hidden successfully\n\n")
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
print("1. AES")
|
| 25 |
+
print("2. Blowfish")
|
| 26 |
+
enc_choice = int(input("What type of encryption do you want? :"))
|
| 27 |
+
print("Your choice is : ", enc_choice)
|
| 28 |
+
|
| 29 |
+
if enc_choice == 1:
|
| 30 |
+
# AES Encryption
|
| 31 |
+
filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 32 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 33 |
+
key = input("Enter your secret key : ")
|
| 34 |
+
aes_chaos.encrypt(filename, key)
|
| 35 |
+
|
| 36 |
+
# AES Decryption
|
| 37 |
+
print("AES Decryption")
|
| 38 |
+
key = input("Enter your secret key : ")
|
| 39 |
+
filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 40 |
+
("All files", "*.*"), ("JPEG files", "*.jpg;*.jpeg"), ("PNG files", "*.png")))
|
| 41 |
+
aes_chaos.decrypt(filename, key)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
elif enc_choice == 2:
|
| 45 |
+
print("Blowfish Encryption")
|
| 46 |
+
# Blowfish Encryption
|
| 47 |
+
key = input("Enter your secret key : ")
|
| 48 |
+
filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 49 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 50 |
+
blowfish.encrypt(filename, key)
|
| 51 |
+
print("Encrypted output saved to output_encrypted.png")
|
| 52 |
+
|
| 53 |
+
# Blowfish Decryption
|
| 54 |
+
filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 55 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 56 |
+
key = input("Enter your secret key : ")
|
| 57 |
+
blowfish.decrypt(filename, key)
|
| 58 |
+
|
| 59 |
+
else:
|
| 60 |
+
print('Invalid choice')
|
| 61 |
+
|
| 62 |
+
print("input the steg image filename")
|
| 63 |
+
steg_filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 64 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 65 |
+
reveal_image(steg_filename)
|
| 66 |
+
|
| 67 |
+
""" UP-SCALING """
|
| 68 |
+
print("UP-SCALING")
|
| 69 |
+
print("input the low res image filename")
|
| 70 |
+
low_res_filename = filedialog.askopenfilename(title="Select Image", filetypes=(
|
| 71 |
+
("PNG files", "*.png"), ("JPEG files", "*.jpg;*.jpeg"), ("All files", "*.*")))
|
| 72 |
+
upscale_image(low_res_filename)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
|
app/models/DEEP_STEGO/Utils/customLossWeight.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tensorflow.keras.losses import mean_squared_error
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# Loss functions
|
| 5 |
+
def custom_loss_1(secret, secret_pred):
|
| 6 |
+
# Compute L2 loss(MSE) for secret image
|
| 7 |
+
secret_mse = mean_squared_error(secret, secret_pred)
|
| 8 |
+
return secret_mse
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def custom_loss_2(cover, cover_predict):
|
| 12 |
+
# Compute L2 loss(MSE) for cover image
|
| 13 |
+
cover_mse = mean_squared_error(cover, cover_predict)
|
| 14 |
+
return cover_mse
|
app/models/DEEP_STEGO/Utils/enhance.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import argparse
|
| 3 |
+
import sys
|
| 4 |
+
import math
|
| 5 |
+
from PIL import ImageFilter, Image
|
| 6 |
+
import cv2
|
| 7 |
+
|
| 8 |
+
'''
|
| 9 |
+
Enhance video by applying denoise and sharpen filters
|
| 10 |
+
'''
|
| 11 |
+
|
| 12 |
+
# Construct argument parser
|
| 13 |
+
parser = argparse.ArgumentParser(description='Use block shuffle')
|
| 14 |
+
parser.add_argument('--denoise', action='store_true', default=False)
|
| 15 |
+
parser.add_argument('--sharpen', action='store_true', default=False)
|
| 16 |
+
parser.add_argument("--input_video", required=True, help="path to input video")
|
| 17 |
+
args = vars(parser.parse_args())
|
| 18 |
+
|
| 19 |
+
# Start video enhancement
|
| 20 |
+
print('\nEnhancing video ...\n')
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# Update progress bar
|
| 24 |
+
def update_progress(current_frame, total_frames):
|
| 25 |
+
progress = math.ceil((current_frame / total_frames) * 100)
|
| 26 |
+
sys.stdout.write('\rProgress: [{0}] {1}%'.format('>' * math.ceil(progress / 10), progress))
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
# Open the input video
|
| 30 |
+
vid_cap = cv2.VideoCapture(args['input_video'])
|
| 31 |
+
|
| 32 |
+
# Total input video frames
|
| 33 |
+
num_frames = int(vid_cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 34 |
+
print("Total frames in input video:", num_frames)
|
| 35 |
+
|
| 36 |
+
# Initialize the video writer
|
| 37 |
+
enhanced_video = cv2.VideoWriter('results/enhanced_secret_300.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 15,
|
| 38 |
+
(300, 300))
|
| 39 |
+
|
| 40 |
+
# Initialize the frame buffer
|
| 41 |
+
frames = []
|
| 42 |
+
|
| 43 |
+
# Load the frames to buffer
|
| 44 |
+
while vid_cap.isOpened():
|
| 45 |
+
success, image = vid_cap.read()
|
| 46 |
+
if success:
|
| 47 |
+
frames.append(image)
|
| 48 |
+
else:
|
| 49 |
+
break
|
| 50 |
+
|
| 51 |
+
# Set up the start frame index
|
| 52 |
+
start_frame = 5
|
| 53 |
+
|
| 54 |
+
# Enhance and save video frame-by-frame
|
| 55 |
+
for i in range(start_frame, len(frames) - (start_frame + 1)):
|
| 56 |
+
output = frames[i]
|
| 57 |
+
if args["denoise"]:
|
| 58 |
+
output = cv2.fastNlMeansDenoisingColoredMulti(frames, i, 11)
|
| 59 |
+
if args["sharpen"]:
|
| 60 |
+
output = np.array(Image.fromarray(output).filter(ImageFilter.DETAIL))
|
| 61 |
+
enhanced_video.write(output)
|
| 62 |
+
update_progress(i, num_frames - (start_frame + 1))
|
| 63 |
+
|
| 64 |
+
# Finish video enhancement
|
| 65 |
+
print('\n\nSuccessfully enhanced video !!!\n')
|
| 66 |
+
|
| 67 |
+
'''
|
| 68 |
+
Sample run:-
|
| 69 |
+
python enhance.py --input_video results/secret_outvid_300.avi --denoise --sharpen
|
| 70 |
+
'''
|
app/models/DEEP_STEGO/Utils/eval.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import random
|
| 3 |
+
import glob
|
| 4 |
+
import sys
|
| 5 |
+
import os
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import matplotlib.pyplot as plt
|
| 8 |
+
from tensorflow.keras.losses import mean_squared_error
|
| 9 |
+
from tensorflow.keras.preprocessing.image import ImageDataGenerator
|
| 10 |
+
from tensorflow.keras.models import load_model
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
|
| 13 |
+
'''
|
| 14 |
+
Evaluates the trained model on a new dataset
|
| 15 |
+
Uses Mean Square Error as evaluation metric
|
| 16 |
+
'''
|
| 17 |
+
|
| 18 |
+
# Path for evaluation dataset
|
| 19 |
+
EVAL_PATH = Path(sys.argv[1]).resolve()
|
| 20 |
+
BATCH_SIZE = 1
|
| 21 |
+
TEST_NUM = len(glob.glob(str(EVAL_PATH)))
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# Normalize input for evaluation
|
| 25 |
+
def normalize_batch(imgs):
|
| 26 |
+
return (imgs - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225])
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
# Denormalize output for prediction
|
| 30 |
+
def denormalize_batch(imgs, should_clip=True):
|
| 31 |
+
imgs = (imgs * np.array([0.229, 0.224, 0.225])) + np.array([0.485, 0.456, 0.406])
|
| 32 |
+
|
| 33 |
+
if should_clip:
|
| 34 |
+
imgs = np.clip(imgs, 0, 1)
|
| 35 |
+
return imgs
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# Create a data generator for evaluation
|
| 39 |
+
test_imgen = ImageDataGenerator(rescale=1. / 255)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
# Compute L2 loss(MSE) for secret image
|
| 43 |
+
def custom_loss_1(secret, secret_pred):
|
| 44 |
+
secret_mse = mean_squared_error(secret, secret_pred)
|
| 45 |
+
return secret_mse
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
# Compute L2 loss(MSE) for cover image
|
| 49 |
+
def custom_loss_2(cover, cover_pred):
|
| 50 |
+
cover_mse = mean_squared_error(cover, cover_pred)
|
| 51 |
+
return cover_mse
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
# Load the trained model
|
| 55 |
+
model = load_model(sys.argv[2], custom_objects={'custom_loss_1': custom_loss_1, 'custom_loss_2': custom_loss_2})
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# Custom data generator
|
| 59 |
+
def generate_generator_multiple(generator, direc):
|
| 60 |
+
genX1 = generator.flow_from_directory(direc, target_size=(224, 224), batch_size=12, shuffle=True, seed=3,
|
| 61 |
+
class_mode=None)
|
| 62 |
+
genX2 = generator.flow_from_directory(direc, target_size=(224, 224), batch_size=12, shuffle=True, seed=8,
|
| 63 |
+
class_mode=None)
|
| 64 |
+
|
| 65 |
+
while True:
|
| 66 |
+
X1i = normalize_batch(genX1.next())
|
| 67 |
+
X2i = normalize_batch(genX2.next())
|
| 68 |
+
|
| 69 |
+
yield ({'secret': X1i, 'cover': X2i},
|
| 70 |
+
{'hide_conv_f': X2i, 'revl_conv_f': X1i}) # Yield both images and their mutual label
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
# Load data using generator
|
| 74 |
+
testgenerator = generate_generator_multiple(test_imgen, direc=str(EVAL_PATH.parent))
|
| 75 |
+
|
| 76 |
+
# Evaluates the model using data generator
|
| 77 |
+
score = model.evaluate(testgenerator, steps=TEST_NUM / BATCH_SIZE, verbose=0)
|
| 78 |
+
|
| 79 |
+
# Print mean square error
|
| 80 |
+
print('Mean square error:', score[0])
|
| 81 |
+
|
| 82 |
+
'''
|
| 83 |
+
Test the model on a random pair of images (test)
|
| 84 |
+
Plots the input and output for verification
|
| 85 |
+
'''
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
# Perform prediction for single input
|
| 89 |
+
def predict(source, cover):
|
| 90 |
+
# Normalize inputs
|
| 91 |
+
secret = np.array(source / 255.0)
|
| 92 |
+
cover = np.array(cover / 255.0)
|
| 93 |
+
|
| 94 |
+
# Predict output
|
| 95 |
+
coverout, secretout = model.predict(
|
| 96 |
+
[normalize_batch(np.reshape(secret, (1, 224, 224, 3))), normalize_batch(np.reshape(cover, (1, 224, 224, 3)))])
|
| 97 |
+
|
| 98 |
+
# Postprocess output cover image
|
| 99 |
+
coverout = denormalize_batch(coverout)
|
| 100 |
+
coverout = np.squeeze(coverout) * 255.0
|
| 101 |
+
coverout = np.uint8(coverout)
|
| 102 |
+
|
| 103 |
+
# Postprocess output secret image
|
| 104 |
+
secretout = denormalize_batch(secretout)
|
| 105 |
+
secretout = np.squeeze(secretout) * 255.0
|
| 106 |
+
secretout = np.uint8(secretout)
|
| 107 |
+
|
| 108 |
+
# Plot output images
|
| 109 |
+
fig_out, ax_out = plt.subplots(1, 2, figsize=(10, 10))
|
| 110 |
+
fig_out.suptitle('Outputs')
|
| 111 |
+
ax_out[0].title.set_text("Secret output")
|
| 112 |
+
ax_out[0].imshow(secretout)
|
| 113 |
+
ax_out[1].title.set_text("Cover output")
|
| 114 |
+
ax_out[1].imshow(coverout)
|
| 115 |
+
print("Prediction Completed!")
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
# Load random test image pairs
|
| 119 |
+
sec, cov = random.sample(os.listdir(str(EVAL_PATH)), k=2)
|
| 120 |
+
|
| 121 |
+
source = np.array(Image.open(str(EVAL_PATH) + '/' + sec))
|
| 122 |
+
cover = np.array(Image.open(str(EVAL_PATH) + '/' + cov))
|
| 123 |
+
|
| 124 |
+
# Plot input images
|
| 125 |
+
fig_in, ax_in = plt.subplots(1, 2, figsize=(10, 10))
|
| 126 |
+
fig_in.suptitle('Inputs')
|
| 127 |
+
ax_in[0].title.set_text("Secret input")
|
| 128 |
+
ax_in[0].imshow(source)
|
| 129 |
+
ax_in[1].title.set_text("Cover input")
|
| 130 |
+
ax_in[1].imshow(cover)
|
| 131 |
+
|
| 132 |
+
# Perform prediction
|
| 133 |
+
predict(source, cover)
|
| 134 |
+
|
| 135 |
+
# Sample run: python eval.py dataset/eval_data checkpoints/steg_model-06-0.03.hdf5
|
app/models/DEEP_STEGO/Utils/preprocessing.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# Preprocessing functions
|
| 5 |
+
def normalize_batch(images):
|
| 6 |
+
"""Performs channel-wise z-score normalization"""
|
| 7 |
+
|
| 8 |
+
return (images - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225])
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def denormalize_batch(images, should_clip=True):
|
| 12 |
+
"""Denormalize the images for prediction"""
|
| 13 |
+
|
| 14 |
+
images = (images * np.array([0.229, 0.224, 0.225])) + np.array([0.485, 0.456, 0.406])
|
| 15 |
+
|
| 16 |
+
if should_clip:
|
| 17 |
+
images = np.clip(images, 0, 1)
|
| 18 |
+
return images
|
app/models/DEEP_STEGO/Utils/progressbarCL_animation.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def update_progress(current_frame, total_frames):
|
| 6 |
+
progress = math.ceil((current_frame/total_frames)*100)
|
| 7 |
+
sys.stdout.write('\rProgress: [{0}] {1}%'.format('>'*math.ceil(progress/10), progress))
|
app/models/DEEP_STEGO/Utils/test.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import sys
|
| 3 |
+
from tensorflow.keras.models import Model
|
| 4 |
+
from tensorflow.keras.utils import plot_model
|
| 5 |
+
from tensorflow.keras.models import load_model
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import matplotlib.pyplot as plt
|
| 8 |
+
from random import randint
|
| 9 |
+
import imageio
|
| 10 |
+
from skimage.util.shape import view_as_blocks
|
| 11 |
+
|
| 12 |
+
'''
|
| 13 |
+
Test the model on sample images (unseen)
|
| 14 |
+
Plot the input and output images
|
| 15 |
+
'''
|
| 16 |
+
|
| 17 |
+
# Load test images
|
| 18 |
+
test_images = np.load(sys.argv[1])
|
| 19 |
+
|
| 20 |
+
# Load model
|
| 21 |
+
model = load_model(sys.argv[2], compile=False)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# Normalize inputs
|
| 25 |
+
def normalize_batch(imgs):
|
| 26 |
+
""" Performs channel-wise z-score normalization """
|
| 27 |
+
|
| 28 |
+
return (imgs - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225])
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# Denormalize outputs
|
| 32 |
+
def denormalize_batch(imgs, should_clip=True):
|
| 33 |
+
imgs = (imgs * np.array([0.229, 0.224, 0.225])) + np.array([0.485, 0.456, 0.406])
|
| 34 |
+
|
| 35 |
+
if should_clip:
|
| 36 |
+
imgs = np.clip(imgs, 0, 1)
|
| 37 |
+
return imgs
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# Load images as batch (batch size -4)
|
| 41 |
+
secretin = test_images[np.random.choice(len(test_images), size=4, replace=False)]
|
| 42 |
+
coverin = test_images[np.random.choice(len(test_images), size=4, replace=False)]
|
| 43 |
+
|
| 44 |
+
# Perform batch prediction
|
| 45 |
+
coverout, secretout = model.predict([normalize_batch(secretin), normalize_batch(coverin)])
|
| 46 |
+
|
| 47 |
+
# Postprocess cover output
|
| 48 |
+
coverout = denormalize_batch(coverout)
|
| 49 |
+
coverout = np.squeeze(coverout) * 255.0
|
| 50 |
+
coverout = np.uint8(coverout)
|
| 51 |
+
|
| 52 |
+
# Postprocess secret output
|
| 53 |
+
secretout = denormalize_batch(secretout)
|
| 54 |
+
secretout = np.squeeze(secretout) * 255.0
|
| 55 |
+
secretout = np.uint8(secretout)
|
| 56 |
+
|
| 57 |
+
# Convert images to UINT8 format (0-255)
|
| 58 |
+
coverin = np.uint8(np.squeeze(coverin * 255.0))
|
| 59 |
+
secretin = np.uint8(np.squeeze(secretin * 255.0))
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# Plot the images
|
| 63 |
+
def plot(im, title):
|
| 64 |
+
fig = plt.figure(figsize=(20, 20))
|
| 65 |
+
|
| 66 |
+
for i in range(4):
|
| 67 |
+
sub = fig.add_subplot(1, 4, i + 1)
|
| 68 |
+
sub.title.set_text(title + " " + str(i + 1))
|
| 69 |
+
sub.imshow(im[i, :, :, :])
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# Plot secret input and output
|
| 73 |
+
plot(secretin, "Secret Input")
|
| 74 |
+
plot(secretout, "Secret Output")
|
| 75 |
+
|
| 76 |
+
# Plot cover input and output
|
| 77 |
+
plot(coverin, "Cover Input")
|
| 78 |
+
plot(coverout, "Cover Output")
|
| 79 |
+
|
| 80 |
+
# Sample run: python test.py test/testdata.npy checkpoints/steg_model-06-0.03.hdf5
|
app/models/DEEP_STEGO/checkpoints/steg_model-06-0.03.hdf5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d2567ad658864875aba9f3c51fde8e2b032d4964b1382298e2d36c62708adceb
|
| 3 |
+
size 32115520
|
app/models/DEEP_STEGO/hide_image.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import tempfile
|
| 3 |
+
import numpy as np
|
| 4 |
+
from tensorflow.keras.models import load_model
|
| 5 |
+
from PIL import Image
|
| 6 |
+
import imageio
|
| 7 |
+
from app.models.DEEP_STEGO.Utils.preprocessing import normalize_batch, denormalize_batch
|
| 8 |
+
|
| 9 |
+
_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models', 'hide.h5')
|
| 10 |
+
_model = None
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _get_model():
|
| 14 |
+
global _model
|
| 15 |
+
if _model is None:
|
| 16 |
+
_model = load_model(_MODEL_PATH)
|
| 17 |
+
return _model
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def hide_image(cover_image_filepath, secret_image_filepath):
|
| 21 |
+
model = _get_model()
|
| 22 |
+
|
| 23 |
+
secret_image_in = Image.open(secret_image_filepath).convert('RGB')
|
| 24 |
+
cover_image_in = Image.open(cover_image_filepath).convert('RGB')
|
| 25 |
+
|
| 26 |
+
if secret_image_in.size != (224, 224):
|
| 27 |
+
secret_image_in = secret_image_in.resize((224, 224))
|
| 28 |
+
if cover_image_in.size != (224, 224):
|
| 29 |
+
cover_image_in = cover_image_in.resize((224, 224))
|
| 30 |
+
|
| 31 |
+
secret_image_in = np.array(secret_image_in).reshape(1, 224, 224, 3) / 255.0
|
| 32 |
+
cover_image_in = np.array(cover_image_in).reshape(1, 224, 224, 3) / 255.0
|
| 33 |
+
|
| 34 |
+
steg_image_out = model.predict([normalize_batch(secret_image_in), normalize_batch(cover_image_in)])
|
| 35 |
+
|
| 36 |
+
steg_image_out = denormalize_batch(steg_image_out)
|
| 37 |
+
steg_image_out = np.squeeze(steg_image_out) * 255.0
|
| 38 |
+
steg_image_out = np.uint8(steg_image_out)
|
| 39 |
+
|
| 40 |
+
_, output_path = tempfile.mkstemp(suffix='.png')
|
| 41 |
+
imageio.imsave(output_path, steg_image_out)
|
| 42 |
+
print("Saved steg image to", output_path)
|
| 43 |
+
|
| 44 |
+
return output_path
|
| 45 |
+
|
| 46 |
+
|
app/models/DEEP_STEGO/models/hide.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d134911e755c063b31d1f2f76678a2b690c5952536bb7c01981cdf6d68e3724b
|
| 3 |
+
size 7692752
|
app/models/DEEP_STEGO/models/hide.h5.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/models/hide.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/models/model_double.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/models/reveal.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f60e937b2957601be10e58df12aaa27b51763449a7883baaf50613500c2dfb32
|
| 3 |
+
size 3102992
|
app/models/DEEP_STEGO/models/reveal.h5.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/models/reveal.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/results/input.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/results/output.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/reveal_image.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import tempfile
|
| 3 |
+
import numpy as np
|
| 4 |
+
from tensorflow.keras.models import load_model
|
| 5 |
+
from PIL import Image
|
| 6 |
+
import imageio
|
| 7 |
+
from app.models.DEEP_STEGO.Utils.preprocessing import normalize_batch, denormalize_batch
|
| 8 |
+
|
| 9 |
+
_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models', 'reveal.h5')
|
| 10 |
+
_model = None
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _get_model():
|
| 14 |
+
global _model
|
| 15 |
+
if _model is None:
|
| 16 |
+
_model = load_model(_MODEL_PATH, compile=False)
|
| 17 |
+
return _model
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def reveal_image(stego_image_filepath):
|
| 21 |
+
model = _get_model()
|
| 22 |
+
|
| 23 |
+
stego_image = Image.open(stego_image_filepath).convert('RGB')
|
| 24 |
+
|
| 25 |
+
if stego_image.size != (224, 224):
|
| 26 |
+
stego_image = stego_image.resize((224, 224))
|
| 27 |
+
|
| 28 |
+
stego_image = np.array(stego_image).reshape(1, 224, 224, 3) / 255.0
|
| 29 |
+
|
| 30 |
+
secret_image_out = model.predict([normalize_batch(stego_image)])
|
| 31 |
+
|
| 32 |
+
secret_image_out = denormalize_batch(secret_image_out)
|
| 33 |
+
secret_image_out = np.squeeze(secret_image_out) * 255.0
|
| 34 |
+
secret_image_out = np.uint8(secret_image_out)
|
| 35 |
+
|
| 36 |
+
_, output_path = tempfile.mkstemp(suffix='.png')
|
| 37 |
+
imageio.imsave(output_path, secret_image_out)
|
| 38 |
+
print("Saved revealed image to", output_path)
|
| 39 |
+
|
| 40 |
+
return output_path
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
|
app/models/DEEP_STEGO/test/cover.png
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/100098.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/101027.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/103006.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/103029.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/104010.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/105027.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/106005.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/106024.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/106025.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/106047.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/107072.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/108004.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/108041.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/108069.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/108070.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/112056.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/112082.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/113016.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/113044.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/12003.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/124084.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/126007.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/130014.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/130026.jpg
ADDED
|
Git LFS Details
|
app/models/DEEP_STEGO/test/images/134008.jpg
ADDED
|
Git LFS Details
|