{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom typing import List, Dict\nfrom tensorflow import keras\nfrom keras import models, layers\n\n!pip install lorem-text\nfrom lorem_text import lorem\n\n!pip install stegano\nfrom stegano import lsb","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-18T08:45:51.540083Z","iopub.execute_input":"2023-10-18T08:45:51.540702Z","iopub.status.idle":"2023-10-18T08:46:08.301686Z","shell.execute_reply.started":"2023-10-18T08:45:51.540672Z","shell.execute_reply":"2023-10-18T08:46:08.300725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SAMPLE_SIZE = 5000\nIMG_DIM = (32, 32)\n\ndef load_imgs(path: str, sample_size: int, dim: (int, int)):\n    data = []\n    for dirname, _, filenames in os.walk(path):\n        for filename in filenames:\n            index = int(filename.split('.')[0])\n            if index < sample_size:\n                bitmap = cv2.imread(os.path.join(dirname, filename))\n                # imread lee las imagenes en BGR. Invertimos los canales a RGB\n                # que es lo que más usado\n                bitmap = cv2.cvtColor(bitmap, cv2.COLOR_BGR2RGB)\n                bitmap = cv2.resize(bitmap, dim)\n                d = {\n                    'filename': filename,\n                    'bitmap': bitmap\n                }\n                data.append(d)\n    data.sort(key=lambda x: x['filename'])\n    return data\n\ncovers = load_imgs('/kaggle/input/alaska2-image-steganalysis/Cover', SAMPLE_SIZE, IMG_DIM)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:46:08.303778Z","iopub.execute_input":"2023-10-18T08:46:08.304046Z","iopub.status.idle":"2023-10-18T08:46:54.619555Z","shell.execute_reply.started":"2023-10-18T08:46:08.304022Z","shell.execute_reply":"2023-10-18T08:46:54.618818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(covers[0]['bitmap'])","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:46:54.620654Z","iopub.execute_input":"2023-10-18T08:46:54.620932Z","iopub.status.idle":"2023-10-18T08:46:54.800248Z","shell.execute_reply.started":"2023-10-18T08:46:54.620908Z","shell.execute_reply":"2023-10-18T08:46:54.799559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Guardo las imagenes para luego volver a leerlas\n!rm -rf '/kaggle/working/tmp/cover'\n!mkdir -p '/kaggle/working/tmp/cover'\n\ndef save_imgs(imgs, path):\n    for img in imgs:\n        img_path = os.path.join(path, img['filename'])\n        bitmap = cv2.cvtColor(img['bitmap'], cv2.COLOR_RGB2BGR)\n        cv2.imwrite(img_path, bitmap)  \n        \nsave_imgs(covers, '/kaggle/working/tmp/cover')","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:46:54.802048Z","iopub.execute_input":"2023-10-18T08:46:54.802309Z","iopub.status.idle":"2023-10-18T08:46:57.610750Z","shell.execute_reply.started":"2023-10-18T08:46:54.802288Z","shell.execute_reply":"2023-10-18T08:46:57.609515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf '/kaggle/working/tmp/lsb'\n!mkdir -p '/kaggle/working/tmp/lsb'\n\ndef write_stego_images(src_path: str, dst_path: str, sample_size: int, hidden_message):\n    for dirname, _, filenames in os.walk(src_path):\n        for filename in filenames:\n            index = int(filename.split('.')[0])\n            if index < sample_size:\n                img_path = os.path.join(dirname, filename)\n                secret = lsb.hide(img_path, hidden_message)\n                secret.save(os.path.join(dst_path, filename))\n\nWORDS = 30\ntext = lorem.words(WORDS)\nprint(text[0:100])\n\nwrite_stego_images(\n    '/kaggle/working/tmp/cover',\n    '/kaggle/working/tmp/lsb',\n    SAMPLE_SIZE,\n    text\n)\n\nstegos = load_imgs('/kaggle/working/tmp/lsb', SAMPLE_SIZE, IMG_DIM)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:46:57.612486Z","iopub.execute_input":"2023-10-18T08:46:57.612740Z","iopub.status.idle":"2023-10-18T08:47:13.327359Z","shell.execute_reply.started":"2023-10-18T08:46:57.612716Z","shell.execute_reply":"2023-10-18T08:47:13.326382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(stegos[0]['bitmap'])","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:13.328990Z","iopub.execute_input":"2023-10-18T08:47:13.329242Z","iopub.status.idle":"2023-10-18T08:47:13.504367Z","shell.execute_reply.started":"2023-10-18T08:47:13.329218Z","shell.execute_reply":"2023-10-18T08:47:13.503641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"diff = np.abs(covers[0]['bitmap'] - stegos[0]['bitmap'])\n\nfig,axes = plt.subplots(ncols=3) \nfig.tight_layout(pad=2.0)\n\naxes[0].imshow(covers[0]['bitmap'])\naxes[0].set_title('cover')\n\naxes[1].imshow(stegos[0]['bitmap'])\naxes[1].set_title('stego')\n\naxes[2].imshow(diff)\naxes[2].set_title('diferencia')","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:13.505526Z","iopub.execute_input":"2023-10-18T08:47:13.505741Z","iopub.status.idle":"2023-10-18T08:47:13.949905Z","shell.execute_reply.started":"2023-10-18T08:47:13.505722Z","shell.execute_reply":"2023-10-18T08:47:13.949219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gray_cover = cv2.cvtColor(covers[0]['bitmap'], cv2.COLOR_RGB2GRAY)\ngray_stego = cv2.cvtColor(stegos[0]['bitmap'], cv2.COLOR_RGB2GRAY)\n\ndiff = np.abs(gray_cover - gray_stego)\n\nfig,axes = plt.subplots(ncols=3) \nfig.tight_layout(pad=2.0)\n\naxes[0].imshow(gray_cover)\naxes[0].set_title('gray_cover')\n\naxes[1].imshow(gray_stego)\naxes[1].set_title('gray_stego')\n\naxes[2].imshow(diff)\naxes[2].set_title('diferencia')","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:13.951029Z","iopub.execute_input":"2023-10-18T08:47:13.951258Z","iopub.status.idle":"2023-10-18T08:47:14.398132Z","shell.execute_reply.started":"2023-10-18T08:47:13.951237Z","shell.execute_reply":"2023-10-18T08:47:14.397457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Armado del dataset\n# 1. Paso las imagenes a gris\ndef gray_imgs(imgs):\n    res = []\n    for img in imgs:\n        r = cv2.cvtColor(img['bitmap'], cv2.COLOR_RGB2GRAY)\n        res.append({'bitmap': r, 'filename': img['filename']})\n    return res\n\ncovers = gray_imgs(covers)\nstegos = gray_imgs(stegos)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:14.399212Z","iopub.execute_input":"2023-10-18T08:47:14.399439Z","iopub.status.idle":"2023-10-18T08:47:14.456439Z","shell.execute_reply.started":"2023-10-18T08:47:14.399419Z","shell.execute_reply":"2023-10-18T08:47:14.455733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig,axes = plt.subplots(ncols=2) \nfig.tight_layout(pad=2.0)\n\naxes[0].imshow(covers[0]['bitmap'])\naxes[0].set_title('cover')\n\naxes[1].imshow(stegos[0]['bitmap'])\naxes[1].set_title('stego')","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:14.458698Z","iopub.execute_input":"2023-10-18T08:47:14.458955Z","iopub.status.idle":"2023-10-18T08:47:14.848375Z","shell.execute_reply.started":"2023-10-18T08:47:14.458935Z","shell.execute_reply":"2023-10-18T08:47:14.847656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 2. Armo los datasets \n# Devuelve un array numpy con todas las imagenes\n# Ver como una lista donde cada elemento es una matriz de altoxancho\n# ej. Si son 100 imagenes de 64x64, devuelve un array de 100x64x64\ndef reshape(imgs, dim):\n    bitmaps = [img['bitmap'] for img in imgs]\n    return np.array(bitmaps).reshape(len(bitmaps), dim[0], dim[1], 1)\n\n# Devuelve un array donde cada elemento es \n# 0 si es cover\n# 1 si es stego\ndef new_categories(covers, stegos):\n    return np.concatenate([np.zeros(len(covers)), np.ones(len(stegos))])\n\n# Armo los datasets de entrenamiento y test\n# Cada dataset es un diccionario con dos listas\n# x: lista con bitmaps de imagen\n# y: lista donde se indica si es stego (1) o es cover (0)\ndef new_dataset(covers, stegos, dim):\n    dataset = {}\n    imgs = covers + stegos\n    dataset[\"x\"] = reshape(imgs, dim)\n    dataset[\"y\"] = new_categories(covers, stegos)\n    return dataset\n    \nsep = int(len(covers) * 0.75)\ntrain = new_dataset(covers[0:sep], stegos[0:sep], IMG_DIM)\ntest = new_dataset(covers[sep:], stegos[sep:], IMG_DIM)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:14.849510Z","iopub.execute_input":"2023-10-18T08:47:14.849730Z","iopub.status.idle":"2023-10-18T08:47:14.869684Z","shell.execute_reply.started":"2023-10-18T08:47:14.849711Z","shell.execute_reply":"2023-10-18T08:47:14.868867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train['x'].shape)\nprint(train['y'].shape)\nprint(test['x'].shape)\nprint(test['y'].shape)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:14.870663Z","iopub.execute_input":"2023-10-18T08:47:14.871036Z","iopub.status.idle":"2023-10-18T08:47:14.875375Z","shell.execute_reply.started":"2023-10-18T08:47:14.871014Z","shell.execute_reply":"2023-10-18T08:47:14.874864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Armado de Red Neuronal\n# Modelo https://dbash.github.io/files/bashkirova%20cnn%20steganalysis.pdf\n\nfrom keras import Input, Model\nfrom keras.layers import Conv2D, Concatenate, Dropout, Flatten, MaxPooling2D, Dense\n\nLAYERS = 32\n\nmodel_input = Input(shape=(IMG_DIM[0], IMG_DIM[1], 1))\nx = Concatenate()([Conv2D(filters=1, kernel_size=(3, 3), activation='relu')(model_input) for i in range(LAYERS)])\nx = MaxPooling2D((2, 2))(x)\nx = Dropout(rate=0.25)(x)\nx = Flatten()(x)\nx = Dense(7200, activation='relu')(x)\nx = Dropout(rate=0.5)(x)\nx = Dense(1, activation='sigmoid')(x)\nmodel = Model(inputs=model_input, outputs=x)\n\n\n# 32 conv\n#model.add(layers.Conv2D(filters=1, kernel_size=(3, 3), activation='relu', input_shape=(IMG_DIM[0], IMG_DIM[1], 1)))\n#model.add(layers.Conv2D(filters=1, kernel_size=(3, 3), activation='relu'))\n\n#model.add(layers.MaxPooling2D((2, 2)))\n#model.add(layers.Dropout(rate=0.25))\n#model.add(layers.Flatten())\n##model.add(layers.Dense(9216, activation='relu'))\n#model.add(layers.Dropout(rate=0.5))\n#model.add(layers.Dense(1, activation='sigmoid'))\n\nmodel.summary()\ntf.keras.utils.plot_model(model, rankdir='LR')","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:14.876117Z","iopub.execute_input":"2023-10-18T08:47:14.876760Z","iopub.status.idle":"2023-10-18T08:47:15.647179Z","shell.execute_reply.started":"2023-10-18T08:47:14.876739Z","shell.execute_reply":"2023-10-18T08:47:15.646467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.utils.plot_model(model)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:15.648181Z","iopub.execute_input":"2023-10-18T08:47:15.648580Z","iopub.status.idle":"2023-10-18T08:47:16.151206Z","shell.execute_reply.started":"2023-10-18T08:47:15.648557Z","shell.execute_reply":"2023-10-18T08:47:16.150473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:16.152372Z","iopub.execute_input":"2023-10-18T08:47:16.152817Z","iopub.status.idle":"2023-10-18T08:47:16.163684Z","shell.execute_reply.started":"2023-10-18T08:47:16.152795Z","shell.execute_reply":"2023-10-18T08:47:16.163011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n  train[\"x\"], \n  train[\"y\"], \n  epochs=100, \n  validation_data=(test[\"x\"], test[\"y\"])\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-18T08:47:16.164961Z","iopub.execute_input":"2023-10-18T08:47:16.165193Z","iopub.status.idle":"2023-10-18T08:54:41.944429Z","shell.execute_reply.started":"2023-10-18T08:47:16.165174Z","shell.execute_reply":"2023-10-18T08:54:41.943645Z"},"trusted":true},"execution_count":null,"outputs":[]}]}