{"cells":[{"metadata":{},"cell_type":"markdown","source":"Libraries"},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install stegano                     # steganalysis library\n!pip install -q efficientnet_pytorch     # Convolutional Neural Net from Google Research","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import stegano\nfrom stegano import lsb\n\n# System\nimport cv2\nimport os, os.path\nfrom PIL import Image              # from RBG to YCbCr\n\n# Basics\nimport pandas as pd\nimport numpy as np\nfrom numpy import pi                # for DCT\nfrom numpy import r_                # for DCT\nimport scipy                        # for cosine similarity\nfrom scipy import fftpack           # for DCT\nimport random\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg    # to check images\n%matplotlib inline\nfrom tqdm.notebook import tqdm      # beautiful progression bar\n\n# SKlearn\nfrom sklearn.model_selection import KFold\nfrom sklearn import metrics\n\n# PyTorch\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch import FloatTensor, LongTensor\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\nimport torch.nn.functional as F\n\n# Data Augmentation for Image Preprocessing\nfrom albumentations import (ToFloat, Normalize, VerticalFlip, HorizontalFlip, Compose, Resize,\n                            RandomBrightness, RandomContrast, HueSaturationValue, Blur, GaussNoise)\nfrom albumentations.pytorch import ToTensorV2, ToTensor\nfrom efficientnet_pytorch import EfficientNet\nfrom torchvision.models import resnet34\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(list(os.listdir(\"../input/v2-effnet-epoch-6-auc-08023\")))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Create a new image with secret message\nmsg_to_hide = \"tan1!!!!!!\"\nsecret = lsb.hide(\"../input/suki-image/capture27.png\", \n                    msg_to_hide, \n                    auto_convert_rgb=True)\nsecret.save(\"./SukiSecret.png\")\n\n# Reveal the hidden message\nprint(lsb.reveal(\"./SukiSecret.png\"))\n\n# See the 2 images side by side (no apparent difference, but WE KNOW the text is there.)\nf, ax = plt.subplots(1, 2, figsize=(14,5))\n                           \noriginal = mpimg.imread('../input/suki-image/capture27.png')\noriginal_plot = ax[0].imshow(original)\n\naltered = mpimg.imread('./SukiSecret.png')\naltered_plot = ax[1].imshow(altered)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\nWe can check how similar are the images by substracting one matrix from the other. \n\nthe **similarity** of the abote 2 images, to see if there is any hidden information in the altered image:"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# From image to array \n# (vectorize the matrix to be able to feed it to the cosine function)\noriginal_vector = np.array(original).flatten()\naltered_vector = np.array(altered).flatten()\n\nprint('Original shape:', original_vector.shape, '\\n' +\n      'Altered shape:', altered_vector.shape)\n\n\n# Distance between the original image and itself (should be 0, because they are identical)\ndist1 = np.sum(original_vector - original_vector)\nprint('Dist1:', dist1)\n\n# Distance between the original image and altered image\ndist2 = np.sum(original_vector - altered_vector)\nprint('Dist2:', dist2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\nThere are 75k files in Cover, JMiPOD, JUNIWARD and UERD and 5k files in Test. We can't read the image arrays all at once, because the available RAM is not enough to perform this task."},{"metadata":{"trusted":true},"cell_type":"code","source":"# ---- STATICS ----\nbase_path = '../input/alaska2-image-steganalysis'\n\ndef read_images_path(dir_name='Cover', test = False):\n    '''series_name: 0001.jpg, 0002.jpg etc.\n    series_paths: is the complete path to a certain image.'''\n    \n    # Get name of the files\n    series_name = pd.Series(os.listdir(base_path + '/' + dir_name))\n    if test:\n        series_name = pd.Series(os.listdir(base_path + '/' + 'Test'))\n    \n    # Create the entire path\n    series_paths = pd.Series(base_path + '/' + dir_name + '/' + series_name)\n    \n    return series_paths","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Read in the data\ncover_paths = read_images_path('Cover', False)\njmipod_paths = read_images_path('JMiPOD', False)\njuniward_paths = read_images_path('JUNIWARD', False)\nuerd_paths = read_images_path('UERD', False)\ntest_paths = read_images_path('Test', True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Show some Images"},{"metadata":{"trusted":true},"cell_type":"code","source":"def show15(title = \"Default\"):\n    '''Shows n amount of images in the data'''\n    plt.figure(figsize=(16,9))\n    plt.suptitle(title, fontsize = 16)\n    \n    for k, path in enumerate(cover_paths[:15]):\n        cover = mpimg.imread(path)\n        \n        plt.subplot(3, 5, k+1)\n        plt.imshow(cover)\n        plt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show15(title = \"15 Original Images\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Images shape, size, data type\n* all images are 512 x 512 x 3\n* all images are of size 786,432 \n* all images are uint8 type"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_sample = mpimg.imread(cover_paths[0])\n\nprint('Image sample shape:', image_sample.shape)\nprint('Image sample size:', image_sample.size)\nprint('Image sample data type:', image_sample.dtype)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\nThere are 3 main different algorithms applied to the original image and used to encode information into it:\n* JMiPOD \n* JUNIWARD\n* UERD\n\n> All images have the corresponding encoding at the same name."},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_images_alg(n = 3, title=\"Default\"):\n    '''Returns a plot of the original Image and Encoded ones.\n    n: number of images to display'''\n    \n    f, ax = plt.subplots(n, 4, figsize=(16, 7))\n    plt.suptitle(title, fontsize = 16)\n    \n\n    for index in range(n):\n        cover = mpimg.imread(cover_paths[index])\n        ipod = mpimg.imread(jmipod_paths[index])\n        juni = mpimg.imread(juniward_paths[index])\n        uerd = mpimg.imread(uerd_paths[index])\n\n        # Plot\n        ax[index, 0].imshow(cover)\n        ax[index, 1].imshow(ipod)\n        ax[index, 2].imshow(juni)\n        ax[index, 3].imshow(uerd)\n        \n        # Add titles\n        if index == 0:\n            ax[index, 0].set_title('Original', fontsize=12)\n            ax[index, 1].set_title('IPod', fontsize=12)\n            ax[index, 2].set_title('Juni', fontsize=12)\n            ax[index, 3].set_title('Uerd', fontsize=12)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_images_alg(n = 3, title = \"Algorithm Difference\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n\n\n Visualizing the data: YCbCr channels"},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_ycbcr_images(n = 3, title = \"Default\"):\n    '''Shows n images as: original RGB, YCbCr and Y, Cb, Cr channels split'''\n    \n    # 4: original image, YCbCr image, Y, Cb, Cr (separate chanels)\n    fig, ax = plt.subplots(n, 5, figsize=(16, 7))\n    plt.suptitle(title, fontsize = 16)\n\n    for index, path in enumerate(cover_paths[:n]):\n        # Read in the original image and convert\n        original_image = Image.open(path)\n        ycbcr_image = original_image.convert('YCbCr')\n        (y, cb, cr) = ycbcr_image.split()\n\n        # Plot\n        ax[index, 0].imshow(original_image)\n        ax[index, 1].imshow(ycbcr_image)\n        ax[index, 2].imshow(y)\n        ax[index, 3].imshow(cb)\n        ax[index, 4].imshow(cr)\n\n        # Add Title\n        if index==0:\n            ax[index, 0].set_title('Original', fontsize=12)\n            ax[index, 1].set_title('YCbCr', fontsize=12)\n            ax[index, 2].set_title('Y', fontsize=12)\n            ax[index, 3].set_title('Cb', fontsize=12)\n            ax[index, 4].set_title('Cr', fontsize=12)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_ycbcr_images(n = 3, title = \"YCbCr Channels\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Visualize DCT Coefficients\n\n\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Read in an Image Example\nimage = mpimg.imread(cover_paths[2])\n\nplt.figure(figsize = (6, 6))\nplt.imshow(image)\nplt.title('Original Image', fontsize=16)\nplt.axis('off');","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Create DCT Function:"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define 2D DCT\ndef dct2(a):\n    # Return the Discrete Cosine Transform of arbitrary type sequence x.\n    return fftpack.dct(fftpack.dct( a, axis=0, norm='ortho' ), axis=1, norm='ortho')\n\n# Perform a blockwise DCT\nimsize = image.shape\ndct = np.zeros(imsize)\n\n# Do 8x8 DCT on image (in-place)\nfor i in r_[:imsize[0]:8]:\n    for j in r_[:imsize[1]:8]:\n        dct[i:(i+8),j:(j+8)] = dct2( image[i:(i+8),j:(j+8)] )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Look at an 8x8 block: original vs DCT coeff"},{"metadata":{"trusted":true},"cell_type":"code","source":"# ---- STATICS ----\npos = 128   # can be changed\n\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n# Display original\nax1.imshow(image[pos:pos+8,pos:pos+8],cmap='gray')\nax1.set_title(\"An 8x8 block : Original Image\", fontsize=16)\n\n# Display the dct of that block\nax2.imshow(dct[pos:pos+8,pos:pos+8],cmap='gray',vmax= np.max(dct)*0.01,vmin = 0, extent=[0,pi,pi,0])\nax2.set_title(\"An 8x8 DCT block\", fontsize = 16);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Display ALL DCT blocks against the original image"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n# Original image\nax1.imshow(image);\nax1.set_title(\"Original Image\", fontsize = 16);\n\n# DCT Blocks\nax2.imshow(dct,cmap='gray',vmax = np.max(dct)*0.01,vmin = 0)\nax2.set_title(\"DCT blocks\", fontsize = 14);","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}