Machine Learning

Ứng dụng Deep Learning vào bài toán giấu tin trong ảnh (Image steganography)

Introduction

Steganography là nghành khoa học nghiên cứu về các phương pháp giấu đi sự tồn tại của thông điệp bí mật (secret message) trong dữ liệu gốc (transportation layers). Trong bài viết lần này, mình sẽ hướng dẫn các bạn một bài toán nhỏ trong Steganography: Image Steganography (giấu tin trong ảnh). Cụ thể hơn, trong bài viết lần này mình sẽ hướng dẫn các bạn cách xây dựng mộ mô hình Convolutional Neural Network để giấu 1 bức ảnh bí mật vào một bức ảnh khác. Bài viết này hướng đến những bạn đã có kiến thức nền tảng về Deep Learning, quen thuộc với Python và thư viện Keras. Các bạn có thể tham khảo thêm tại repo này của mình.

OK, let's get started.

Before we start

Image Steganography không phải là một ngành nghiên cứu mới, nó đã tồn tại trong nhiều thập kỉ qua. Một trong những phương pháp truyền thống để giấu tin trong ảnh là Least Significant Bit - thay đổi 1 hoặc 2 bit cuối của ảnh để chèn vào thông tin cần giấu đi. Phươn pháp này có ưu điểm là rất dễ dàng thực hiện, tuy nhiên nó cũng rất dễ bị phát hiện. Trong những năm gần đây, Deep Learning đã và đang được ứng dụng nhiều vào trong các bài toán giấu tin, đặc biệt là bài toán giấu tin trong ảnh. Nhiệm vụ cần làm trong Image Steganography là giấu một ảnh bí mật (secret image) vào trong một bức ảnh khác (cover image). Có 2 thách thức lớn trong Image Steganography:

  • Ảnh cover image trước và sau khi giấu secret image không được thay đổi quá nhiều.
  • Ảnh secret sau khi được decode từ ảnh cover phải giống với ảnh secret ban đầu.

Hướng tiếp cận chính là xây dựng một mô hình Deep Convolutional Neural Network bao gồm 2 mạng CNN nhỏ: Hiding Network - có vai trò "giấu" secret image vào cover image và Revealing network - giải mã ảnh secret từ ảnh cover sau để khôi phục bức ảnh gốc. Các bạn có thể xem thêm trong bức hình phía dưới để hiểu rõ hơn về luồng hoạt động của hệ thống.

Prepare the data for training

Đây là một bài toán Unsupervised learning nên dữ liệu các bạn cần chuẩn bị rất đơn giản: 1 folder dành cho việc training, 1 folder phục vụ quá trình validate. Ảnh để train và validate có thể là bất cứ ảnh nào mà bạn muốn.

image_steganography/
├── train_image
│   ├── train_image_1.jpg
│   ├── train_image_2.jpg
│   ├── train_image_3.jpg
│   └── train_image_4.jpg
│   └── ...
└── validate_image
    ├── validate_image_1.jpg
    ├── validate_image_2.jpg
    ├── validate_image_3.jpg
    └── validate_image_4.jpg
    └── ...

Số lượng ảnh để train và validate các bạn tùy chình theo ý muốn, tuy nhiên mình khuyến khích các bạn nên chuẩn bị khoảng 1000 ảnh để train và khoảng 400 ảnh để validate.

Build & train the model

Như trong hình minh họa phía trên, ta cần xây dựng 2 mô hình tách biệt nhau: Hiding Network và Revealing Network. Trong bài viết này mình sẽ hướng dẫn các bạn xây dựng cả 2 mô hình trên với 1 kiến trúc CNN đơn giản, các bạn có thể tùy chỉnh mạng theo ý muốn. Chi tiết các bạn xem trong file utils.py

Import các thư viện cần thiết:

import os
from keras.models import *
from keras.layers import *
from keras.callbacks import *
from keras.optimizers import *
import cv2
import numpy as np
def build_model():
    secret_iamge = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, IMAGE_CHANNEL), name="secret_image")
    cover_image = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, IMAGE_CHANNEL), name="cover_image")
    ...
    encode_decoder = Model(inputs=[secret_iamge, cover_image], outputs=[
        container_image, decoded_image])
    print (encode_decoder.summary())
    return encode_decoder

Bước tiếp theo là viết 1 hàm để sinh dữ liệu trong quá trình training. Hàm này có nhiện vụ chọn 2 ảnh ngẫu nhiên trong folder train hoặc validate, resize ảnh về kích thước phù hợp và normalize ảnh (chia 255). Bên cạnh đó, bạn cũng cần định nghĩa các tham số để chuẩn bị cho quá trình training như kích thước ảnh, số kênh của ảnh, kích thước 1 batch, tên folder chứa ảnh để train và validate.

IMAGE_SIZE = 256
IMAGE_CHANNEL = 3
BATCH_SIZE = 8
TRAIN_FOLDER = './train_image'
VALIDATE_FOLDER = './validate_image'


def load_image(image_path):
    image = cv2.imread(image_path)
    image = cv2.resize(image, (IMAGE_SIZE, IMAGE_SIZE))
    return image / 255.


def generate_data(image_list):
    while True:
        image_1_batch = []
        image_2_batch = []
        for ind in range(BATCH_SIZE):
            image_1 = load_image(random.choice(image_list))
            image_2 = load_image(random.choice(image_list))
            image_1_batch.append(image_1)
            image_2_batch.append(image_2)
        yield ({'secret_image': np.array(image_1_batch), 'cover_image': np.array(image_2_batch)},
            {'decoded_image': np.array(image_1_batch), 'container_image': np.array(image_2_batch)})

Hàm loss được định nghĩa cho mô hình là Mean Square Error (MSE) giữa 2 cặp ảnh: cover image - container image, secret image - revealed image như trong công thức dưới đây:

L=cc+βssL = \| c - c' \| + \beta \| s - s' \|

với:

  • LL: hàm loss để tối ưu trong quá trình training
  • cc: cover image
  • cc': container image
  • ss: secret image
  • ss': revealed image
  • Tham số β\beta giúp điều chỉnh mô hình CNN thiên về tối ưu cho cặp cover-container image hay cặp secret-revealed image hơn. Trong code mình để tham số β=1\beta=1, các bạn có thể điều chỉnh β\beta tùy ý muốn. Ok. Build model xong xuôi rồi, ta định nghĩa các optimizer, callbacks và compile model để traing thôi.
MODEL_PATH = './model/model_{val_loss:.5f}.h5'
if not os.path.exists('./model'):
    os.mkdir('./model')

model = build_model()
optimizer = Adam(lr=0.00001)
model.compile(optimizer=optimizer, loss={'decoded_image': 'mse', 'container_image': 'mse'}, loss_weights={
              'decoded_image': 1., 'container_image': 1.})
train_image_list = os.listdir(TRAIN_FOLDER)
train_image_list = [os.path.join(TRAIN_FOLDER, i) for i in train_image_list]
validate_image_list = os.listdir(VALIDATE_FOLDER)
validate_image_list = [os.path.join(VALIDATE_FOLDER, i) for i in validate_image_list]
check_point = ModelCheckpoint(MODEL_PATH, verbose=True, save_best_only=True)
early_stop = EarlyStopping(patience=5, verbose=True)
model.fit_generator(generate_data(train_image_list),
                    steps_per_epoch=500, epochs=500, validation_data=generate_data(validate_image_list),
                    validation_steps=100, callbacks=[check_point, early_stop])

Thời gian training phụ thuộc rất nhiều vào cấu hình phần cứng, máy của mình chỉ có 1 card 1080Ti nên thời gian hơi lâu, khoảng 3 phút trên 1 epoch.

100/100 [==============================] - 190s 2s/step - loss: 0.2582 - container_image_loss: 0.1408 - decoded_image_loss: 0.1174 - val_loss: 0.1543 - val_container_image_loss: 0.1173 - val_decoded_image_loss: 0.0370

Epoch 00001: val_loss improved from inf to 0.15425, saving model to ./model/model_0.15425.h5
Epoch 2/500
100/100 [==============================] - 178s 2s/step - loss: 0.1390 - container_image_loss: 0.1128 - decoded_image_loss: 0.0262 - val_loss: 0.1182 - val_container_image_loss: 0.1025 - val_decoded_image_loss: 0.0157

Epoch 00002: val_loss improved from 0.15425 to 0.11825, saving model to ./model/model_0.11825.h5
Epoch 3/500
100/100 [==============================] - 177s 2s/step - loss: 0.1105 - container_image_loss: 0.0963 - decoded_image_loss: 0.0142 - val_loss: 0.1074 - val_container_image_loss: 0.0960 - val_decoded_image_loss: 0.0114

Epoch 00003: val_loss improved from 0.11825 to 0.10742, saving model to ./model/model_0.10742.h5

Kết quả khá là ấn tượng với model sau 15 epochs. 2 hình đầu tiên là cặp ảnh cover image - container image, cặp ảnh tiếp theo là secret image và revealed image. Ta có thể nhận thấy rõ là sau khi giấu ảnh secret, ảnh cover gần như không có sự thay đổi gì, mắt thường rất khó nhận ra. Tương tự đối với cặp ảnh secret - revealed image, 2 ảnh gần như giống nhau hoàn toàn, khó có thể phân biệt được bằng mắt thường.

Conclusion

Trong bài viết này mình đã hướng dẫn các bạn cách ứng dụng Deep Learning vào bài toán giấu tin trong ảnh. Hy vọng bài viết này của mình có thể giúp ích cho các bạn đang muốn tìm hiểu về lĩnh vực giấu tin hoặc những bạn đang muốn học thêm về Deep Learning. Hẹn gặp lại các bạn vào các bài viết sau.

Registration Login
Sign in with social account
or
Lost your Password?
Registration Login
Sign in with social account
or
A password will be send on your post
Registration Login
Registration