{"cells":[{"metadata":{},"cell_type":"markdown","source":"![](https://article1000.com/wp-content/uploads/2017/08/steganography-hiding-your-secrets-with-php-23-638.jpg)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"As this competition is now a bit old i think that what is the task and what are we coding to achieve but if you are new to this competition than i will try to expain the motive of this competition to you so in this you’ll create an efficient and reliable method to detect secret data hidden within innocuous-seeming digital images don't panic you just have to create a model that classifies the image into category of image that is embedded with hidden message or image which has no information hidden in it as this clearly explained by the hosts .**\"The goal of the competition is to determine which of the images in the test set (Test/) have hidden messages embedded.\"**","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"So what is the motive of this notebook. So to understand the motive you should know why is image processing needed and why it is important you can see \n1. https://www.kaggle.com/tanulsingh077/steganalysis-complete-understanding-and-model this is a great starting point as it significantly explains the task of what is task for the competition and how can we model the problem\n2. https://www.kaggle.com/ninjakx01/alaska2-image-analysis-in-spatial-freq-domain this is also a very good notebook for image processing i too have borrowed a some of code from it","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"<font color=\"red\" size=3>Please UPVOTE this kernel if you like it. It motivates me to produce more quality content :) <br><br>\n    Please do comment what your views are and what you understand from this.\n    <br><br> Dont't forget to give your suggestions in the comment section </font>","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"!pip install opencv-contrib-python","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np \nimport cv2\nimport os\nfrom pathlib import Path\nimport matplotlib.pyplot as plt\nimport matplotlib\nfrom PIL import Image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path = Path('/kaggle/input/alaska2-image-steganalysis')\nfolders = ['Cover', 'JMiPOD', 'JUNIWARD', 'UERD']\nimg_num = 5\nimg_cov_path = f\"{path}/{folders[0]}/0000{img_num}.jpg\"\nimg_jmi_path = f\"{path}/{folders[1]}/0000{img_num}.jpg\"\nimg_juni_path = f\"{path}/{folders[2]}/0000{img_num}.jpg\"\nimg_uerd_path = f\"{path}/{folders[3]}/0000{img_num}.jpg\"\nimg_cov = cv2.imread(img_cov_path, cv2.IMREAD_GRAYSCALE)\nimg_jmi = cv2.imread(img_juni_path, cv2.IMREAD_GRAYSCALE)\nimg_juni = cv2.imread(img_juni_path, cv2.IMREAD_GRAYSCALE)\nimg_uerd = cv2.imread(img_uerd_path, cv2.IMREAD_GRAYSCALE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def subtract_median_bg_image(im):\n    k = np.max(im.shape)//20*2+1\n    bg = cv2.medianBlur(im, k)\n    return cv2.addWeighted (im, 4, bg, -4, 128)\n\ndef subtract_gaussian_bg_image(im):\n    k = np.max(im.shape)/10\n    bg = cv2.GaussianBlur(im ,(0,0) ,k)\n    return cv2.addWeighted (im, 4, bg, -4, 128)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"1. Brightness is very well known image adjustments<br>\nFor brightness adjustments we will use gamma as it defines pixel's numerical value and its actual luminance. Without gamma, shades captured by digital cameras wouldn't appear as they did to our eyes (on a standard monitor) this gamma value defines the illuminance of pixels<br>\n\ngamma = 1.0![](https://cdn.cambridgeincolour.com/images/tutorials/gamma_example-g10b.jpg)\ngamma = 1/2.2![](https://cdn.cambridgeincolour.com/images/tutorials/gamma_example-g22b.jpg)\n\n2. Contrast Streching\nContrast stretching (often called normalization) is a simple image enhancement technique that attempts to improve the contrast in an image by stretching the range of intensity values it contains to span a desired range of values<br>\nInitial Image\n![](https://homepages.inf.ed.ac.uk/rbf/HIPR2/images/moo2.gif)\nImage after \n![](https://homepages.inf.ed.ac.uk/rbf/HIPR2/images/moo2str1.gif)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def adjust_gamma(image, gamma):\n    # build a lookup table mapping the pixel values [0, 255] to\n    # their adjusted gamma values\n    invGamma = 1.0 / gamma\n    table = np.array([((i / 255.0) ** invGamma) * 255\n                for i in np.arange(0, 256)]).astype(\"uint8\")\n    \n    # apply gamma correction using the lookup table\n    return cv2.LUT(image, table)\n\ndef contrast_stretching(img):        \n    rr, gg, bb = cv2.split(img)    \n    imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    \n    im = imgray    \n    ih, iw = imgray.shape    \n    (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(imgray)    \n    for i in range(ih):        \n        for j in range(iw):            \n            im[i, j] = 255 * ((gg[i, j] - minVal) / (maxVal - minVal))        \n    limg = cv2.merge((rr, im, bb))    \n    return limg","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"3. Histogram Normalization \nHistogram modeling techniques (e.g. histogram equalization) provide a good method for modifying the dynamic range and contrast of an image by altering that image such that its intensity histogram has a desired shape. this employs a monotonic, non-linear mapping which re-assigns the intensity values of pixels in the input image such that the output image contains a uniform distribution of intensities (flat histogram)<br>\n\nInitial Image\n![](https://homepages.inf.ed.ac.uk/rbf/HIPR2/images/moo2.gif)\nAfter Image\n![](https://homepages.inf.ed.ac.uk/rbf/HIPR2/images/moo2heq1.gif)\nIt differs from the more sophisticated histogram equalization in that it can only apply a linear scaling function to the image pixel values. As a result the resulting image is less harsh.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def match_imgs(img1_path, img2_path):\n    img1 = Image.open(img1_path)\n    img2 = Image.open(img2_path)\n    \n    if img1.mode != img2.mode:\n        log.warning('Unequal image modes (%s vs %s) - converting %s to %s',\n                    img1.mode, img2.mode, img1.mode, img2.mode)\n        img1 = img1.convert(img2.mode)\n    if img1.width != img2.width or img1.height != img2.height:\n        log.warning('Dimensions do not match ([%d, %d] vs [%d, %d])',\n                    img1.width, img1.height, img2.width, img2.height)\n    return img1, img2\n\ndef diffed_imgs(img1, img2):\n    \"\"\" Blatantly checking which pixels are different\"\"\"\n    for y in range(min(img1.height, img2.height)):\n        for x in range(min(img1.width, img2.width)):\n            img1_pixel = img1.getpixel((x, y))\n            img2_pixel = img2.getpixel((x, y))\n            if img1_pixel != img2_pixel:\n                yield (x, y), img1_pixel, img2_pixel\n\n\ndef find_diffs(orig_path, stego_path, out_path='file.jpg'):\n    \"\"\"Running function of the above code\"\"\"\n    orig, stego = match_imgs(orig_path, stego_path)\n    out = Image.new('RGB', orig.size, (0, 0, 0)) if out_path else None\n    for pos, orig_pixel, stego_pixel in diffed_imgs(orig, stego):\n#         log.info('Mismatched pixels at %s: %s vs %s', pos, orig_pixel,\n#                  stego_pixel)\n        if out:\n            out.putpixel(pos, (255, 255, 255))\n\n    if out:\n        out.save(out_path)\n    a = stego_path.split('/')[-2]\n    fig, ax = plt.subplots(figsize=(20, 5))\n    im = plt.imread(out_path)\n    plt.subplot(141)\n    adjusted_15 = adjust_gamma(im, gamma=.5)\n    plt.title('Pixel differe '+ a + 'with gamma .5')\n    plt.imshow(adjusted_15)   \n    plt.subplot(142)\n    adjusted_75 = adjust_gamma(im, gamma=.75)\n    plt.title('Pixel differe '+ a + 'with gamma .75')\n    plt.imshow(adjusted_15) \n    plt.subplot(143)\n    adjusted_150 = adjust_gamma(im, gamma=1.5)\n    plt.title('Pixel differe '+ a + 'with gamma 1.5')\n    plt.imshow(adjusted_15) \n    plt.subplot(144)\n    adjusted_15 = adjust_gamma(im, gamma=2)\n    plt.title('Pixel differe '+ a + 'with gamma 2')\n    plt.imshow(adjusted_15) \n\ndef histogram_normalization(image):    \n    hist,bins = np.histogram(image.flatten(),256,[0,256])    \n    cdf = hist.cumsum()   \n    # cdf_normalized = cdf * hist.max()/ cdf.max()    \n    cdf_m = np.ma.masked_equal(cdf,0)    \n    cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())    \n    cdf = np.ma.filled(cdf_m,0).astype('uint8')     \n    img2 = cdf[image]    \n    return img2\n\n\ndef matching(source,template):    \n    oldshape = source.shape    \n    source1 = source.ravel()    \n    template1 = template.ravel()    \n    s_values, bin_idx, s_counts = np.unique(source1, return_inverse=True,return_counts=True)    \n    t_values, t_counts = np.unique(template1, return_counts=True)    \n    s_quantiles = np.cumsum(s_counts).astype(np.float64)    \n    s_quantiles /= s_quantiles[-1]    \n    t_quantiles = np.cumsum(t_counts).astype(np.float64)    \n    t_quantiles /= t_quantiles[-1]    \n    interp_t_values = np.interp(s_quantiles, t_quantiles, t_values)    \n    interp_t_values1=interp_t_values.astype(np.uint8)    \n    sub=interp_t_values-interp_t_values1    \n    interp_t_values1[sub>.5]+=1    \n    match_v1=interp_t_values1[bin_idx].reshape(oldshape).astype(np.uint8)       \n    return match_v1\n\n\n\ndef Histo_Specification(source, template):    \n    f=[]    \n    for x in range(0,3):        \n        f.append(matching(source[:,:,x], template[:,:,x]))    \n    img = cv2.merge((f[0],f[1],f[2]))     \n    return img\n\n\ndef histogram_normalization(image):    \n    hist,bins = np.histogram(image.flatten(),256,[0,256])    \n    cdf = hist.cumsum()   \n    # cdf_normalized = cdf * hist.max()/ cdf.max()    \n    cdf_m = np.ma.masked_equal(cdf,0)    \n    cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())    \n    cdf = np.ma.filled(cdf_m,0).astype('uint8')     \n    img2 = cdf[image]    \n    return img2\n\ndef diffed_imgs_plt(img1,img2,out_path='file.jpg',cont=True,hist=True):\n    img1 = Image.fromarray(img1)\n    img2 = Image.fromarray(img2)\n    if img1.mode != img2.mode:\n        img1 = img1.convert(img2.mode)\n    out = Image.new('RGB', img1.size, (0, 0, 0))\n    for pos, orig_pixel, stego_pixel in diffed_imgs(img1, img2):\n#         log.info('Mismatched pixels at %s: %s vs %s', pos, orig_pixel,\n#                  stego_pixel)\n        if out:\n            out.putpixel(pos, (255, 255, 255))\n\n    if out:\n        out.save(out_path)\n    im = plt.imread(out_path)\n    final = cv2.cvtColor(im, cv2.COLOR_LAB2BGR)\n    matplotlib.rc('figure', figsize=[7, 7])\n    if cont == True:\n        try:\n            final = contrast_stretching(final)\n        except:\n            pass\n    if hist == True:\n        try:\n            final = histogram_normalization(final)\n        except:\n            pass\n    plt.imshow(final)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"find_diffs(img_cov_path,img_jmi_path)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The results are of Pixel difference between the original image and the JMiPOD stegno image with gamma correction","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"4. Now i will try and see the results of using **CLAHE (Contrast Limited Adaptive Histogram Equalization)** <br>\nI will not describe it as it is rather very well explained in the opencv documentation<br>\n\"\"In adaptive histogram equalization the image is divided into small blocks called \"tiles\" . Then each of these blocks are histogram equalized. So in a small area, histogram would confine to a small region. If noise is there, it will be amplified. To avoid this, contrast limiting is applied. If any histogram bin is above the specified contrast limit (by default 40 in OpenCV), those pixels are clipped and distributed uniformly to other bins before applying histogram equalization. After equalization, to remove artifacts in tile borders, bilinear interpolation is applied.\"\" -> **OpenCV**\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_the_diff(img_cov_path = img_cov_path,img_jmi_path = img_jmi_path,\n                  img_juni_path = img_juni_path , img_uerd_path = img_uerd_path,\n                 cont =False ,hist=False):\n    \n    a = img_cov_path.split('/')[-2]\n    b = img_jmi_path.split('/')[-2]\n    c = img_juni_path.split('/')[-2]\n    d = img_uerd_path.split('/')[-2]\n    fig, ax = plt.subplots(figsize=(20, 5))\n    plt.subplot(141)\n    im = cv2.imread(img_cov_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl1 = clahe.apply(l)\n    diffed_imgs_plt(cl1,cl1,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w '+ a + '/' + a)\n    \n    plt.subplot(142)\n    im = cv2.imread(img_jmi_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl2 = clahe.apply(l)\n    diffed_imgs_plt(cl1,cl2,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w ' + a + '/' + b)\n\n    plt.subplot(143)\n    im = cv2.imread(img_juni_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl3 = clahe.apply(l)\n    diffed_imgs_plt(cl1,cl3,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w '+ a + '/' + c)\n\n    plt.subplot(144)\n    im = cv2.imread(img_uerd_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n    \n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl4 = clahe.apply(l)\n    diffed_imgs_plt(cl1,cl4,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w '+ a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_the_diff()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Okay so we can see clear difference between the cover and JMiPOD ,cover and JUNIWARD,Cover with Uerd this shows very pleasing different between the different segnography techniques and non stegnography images note- we have not used contrast streaching and histogram normalization because CLAHE takes care of it","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Following cells are just experiments of applying contrast streching and Normalization after Pixel differencing is done(to see how it works please see the **'diffed_img_plt'** function above ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_the_diff(cont = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_the_diff(hist = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_the_diff(cont=True,hist=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can see some interesting results of applying histogram normalization and contrast streaching after pixel differencing as more and more \nintriguing differences between images can be found","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def diff_histo(img_cov_path = img_cov_path,img_jmi_path = img_jmi_path,\n                  img_juni_path = img_juni_path , img_uerd_path = img_uerd_path,\n                  cont = True,hist=True):\n    \n    a = img_cov_path.split('/')[-2]\n    b = img_jmi_path.split('/')[-2]\n    c = img_juni_path.split('/')[-2]\n    d = img_uerd_path.split('/')[-2]\n    fig, ax = plt.subplots(figsize=(20, 5))\n    plt.subplot(141)\n    im = cv2.imread(img_cov_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl1 = clahe.apply(l)\n    cl2 = cl1\n    cl3 = cl1\n    img = cv2.merge((cl1,cl2,cl3))\n    cl1 = Histo_Specification(img, img)\n    diffed_imgs_plt(cl1,cl1,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w ' + a + '/' + a)\n    \n    plt.subplot(142)\n    im = cv2.imread(img_jmi_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl1 = clahe.apply(l)\n    cl2 = cl1\n    cl3 = cl1\n    img1 = cv2.merge((cl1,cl2,cl3))\n    cl2 = Histo_Specification(img, img1)\n    diffed_imgs_plt(cl1,cl2,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w ' + a + '/' + b)\n\n    plt.subplot(143)\n    im = cv2.imread(img_juni_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n\n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl1 = clahe.apply(l)\n    cl2 = cl1\n    cl3 = cl1\n    img2 = cv2.merge((cl1,cl2,cl3))\n    cl3 = Histo_Specification(img, img2)\n    diffed_imgs_plt(cl1,cl3,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w ' + a + '/' + c)\n\n    plt.subplot(144)\n    im = cv2.imread(img_uerd_path)\n    im = subtract_median_bg_image(im)\n    lab= cv2.cvtColor(im, cv2.COLOR_BGR2LAB)\n\n    l, x, y = cv2.split(lab)\n    \n    #-----Applying CLAHE to L-channel-------------------------------------------\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    cl1 = clahe.apply(l)\n    cl2 = cl1\n    cl3 = cl1\n    img3 = cv2.merge((cl1,cl2,cl3))\n    cl4 = Histo_Specification(img, img3)\n    diffed_imgs_plt(cl1,cl4,cont = cont , hist = hist)\n    plt.title('Pixel differe b/w ' + a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"diff_histo()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Root_Channel_SQUR(crop):    \n    blu=crop[:,:,0].astype(np.int32)    \n    gre=crop[:,:,1].astype(np.int32)    \n    red=crop[:,:,2].astype(np.int32)      \n    lll=(((blu**2)+(gre**2)+(red**2))/float(3))**0.5    \n    lll=lll.astype(np.uint8)#1st version of image    \n    return lll\n\n\na = img_cov_path.split('/')[-2]\nb = img_jmi_path.split('/')[-2]\nc = img_juni_path.split('/')[-2]\nd = img_uerd_path.split('/')[-2]\nim = cv2.imread(img_cov_path)\nRoot_Channel_SQUR_image = Root_Channel_SQUR(im)\nim = subtract_median_bg_image(im)\nRoot_Channel_SQUR_image = subtract_median_bg_image(Root_Channel_SQUR_image)\nplt.imshow(Root_Channel_SQUR_image)\n\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(141)\nim = cv2.imread(img_cov_path)\nRoot_Channel_SQUR_image = Root_Channel_SQUR(im)\nim = subtract_median_bg_image(im)\nRoot_Channel_SQUR_image = subtract_median_bg_image(Root_Channel_SQUR_image)\ndiffed_imgs_plt(Root_Channel_SQUR_image,Root_Channel_SQUR_image)\nplt.title('Pixel differe b/w ' + a + '/' + a)\n\nplt.subplot(142)\nim1 = cv2.imread(img_juni_path)\nRoot_Channel_SQUR_image1 = Root_Channel_SQUR(im1)\nim1 = subtract_median_bg_image(im1)\nRoot_Channel_SQUR_image1 = subtract_median_bg_image(Root_Channel_SQUR_image1)\ndiffed_imgs_plt(Root_Channel_SQUR_image,Root_Channel_SQUR_image1)\nplt.title('Pixel differe b/w ' + a + '/' + b)\n\nplt.subplot(143)\nim2 = cv2.imread(img_jmi_path)\nRoot_Channel_SQUR_image2 = Root_Channel_SQUR(im2)\nim2 = subtract_median_bg_image(im2)\nRoot_Channel_SQUR_image2 = subtract_median_bg_image(Root_Channel_SQUR_image2)\ndiffed_imgs_plt(Root_Channel_SQUR_image,Root_Channel_SQUR_image2)\nplt.title('Pixel differe b/w ' + a + '/' + c)\n\nplt.subplot(144)\nim3 = cv2.imread(img_uerd_path)\nRoot_Channel_SQUR_image3 = Root_Channel_SQUR(im3)\nim3 = subtract_median_bg_image(im3)\nRoot_Channel_SQUR_image3 = subtract_median_bg_image(Root_Channel_SQUR_image3)\ndiffed_imgs_plt(Root_Channel_SQUR_image,Root_Channel_SQUR_image3)\nplt.title('Pixel differe b/w ' + a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Root_Channel_SQUR** in this function different channels values are just squared,added and then we take square root of values leading us to have a single channel of image. the squaring and then adding leads to increase which is then further drowned by taking the root","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def Krischer(crop):    \n    Input=crop[:,:,1]    \n    a,b=Input.shape    \n    Kernel=np.zeros((3,3,8))#windows declearations(8 windows)    \n    Kernel[:,:,0]=np.array([[5,5,5],[-3,0,-3],[-3,-3,-3]])     \n    Kernel[:,:,1]=np.array([[-3,5,5],[-3,0,5],[-3,-3,-3]])    \n    Kernel[:,:,2]=np.array([[-3,-3,5],[-3,0,5],[-3,-3,5]])    \n    Kernel[:,:,3]=np.array([[-3,-3,-3],[-3,0,5],[-3,5,5]])    \n    Kernel[:,:,4]=np.array([[-3,-3,-3],[-3,0,-3],[5,5,5]])    \n    Kernel[:,:,5]=np.array([[-3,-3,-3],[5,0,-3],[5,5,-3]])    \n    Kernel[:,:,6]=np.array([[5,-3,-3],[5,0,-3],[5,-3,-3]])    \n    Kernel[:,:,7]=np.array([[5,5,-3],[5,0,-3],[-3,-3,-3]])    \n    #Kernel=(1/float(15))*Kernel    \n    #Convolution output    \n    dst=np.zeros((a,b,8))    \n    for x in range(0,8):        \n        dst[:,:,x] = cv2.filter2D(Input,-1,Kernel[:,:,x])    \n    Out=np.zeros((a,b))    \n    for y in range(0,a-1):        \n        for z in range(0,b-1):            \n            Out[y,z]=max(dst[y,z,:])    \n    Out=np.uint8(Out)            \n    return Out\n\n\na = img_cov_path.split('/')[-2]\nb = img_jmi_path.split('/')[-2]\nc = img_juni_path.split('/')[-2]\nd = img_uerd_path.split('/')[-2]\nim = cv2.imread(img_cov_path)\nKrisch = Krischer(im)\nim = subtract_median_bg_image(im)\nKrisch = subtract_median_bg_image(Krisch)\nplt.imshow(Krisch)\n\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(141)\nim = cv2.imread(img_cov_path)\nKrisch = Krischer(im)\nim = subtract_median_bg_image(im)\nKrisch = subtract_median_bg_image(Krisch)\ndiffed_imgs_plt(Krisch,Krisch)\nplt.title('Pixel differe b/w ' + a + '/' + a)\n\nplt.subplot(142)\nim1 = cv2.imread(img_juni_path)\nKrisch1 = Krischer(im1)\nim1 = subtract_median_bg_image(im1)\nKrisch1 = subtract_median_bg_image(Krisch1)\ndiffed_imgs_plt(Krisch,Krisch1)\nplt.title('Pixel differe b/w ' + a + '/' + b)\n\nplt.subplot(143)\nim2 = cv2.imread(img_jmi_path)\nKrisch2 = Krischer(im2)\nim2 = subtract_median_bg_image(im2)\nKrisch2 = subtract_median_bg_image(Krisch2)\ndiffed_imgs_plt(Krisch,Krisch2)\nplt.title('Pixel differe b/w ' + a + '/' + c)\n\nplt.subplot(144)\nim3 = cv2.imread(img_uerd_path)\nKrisch3 = Krischer(im3)\nim3 = subtract_median_bg_image(im3)\nKrisch3 = subtract_median_bg_image(Krisch3)\ndiffed_imgs_plt(Krisch,Krisch3)\nplt.title('Pixel differe b/w ' + a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The **Kirsch operator** or Kirsch compass kernel is a non-linear edge detector that finds the maximum edge strength in a few predetermined directions. It is named after the computer scientist Russell A. Kirsch. --> wiki<br>\nThis filter is very easy to code and is very versitile in detecting the edges in all of the eight directions.First every filter is convolved over the image and than the max of the filtered values are intercepted after this the differencing is done. according to the images above kirsch filter perform well to detect the anomalities.\n![](https://wikimedia.org/api/rest_v1/media/math/render/svg/7d0ec899c8248a8a2e38e7e71f17a1f6772c5b92)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"**HOG(Histogram of Oriented Gradients)** is a feature descriptor that is often used to extract features from image data. It is widely used in computer vision tasks for object detection.The HOG descriptor focuses on the structure or the shape of an object. The HOG feature descriptor counts the occurrences of gradient orientation in localized portions of an image.\n![](https://www.learnopencv.com/wp-content/uploads/2016/12/hog-cell-gradients.png)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from skimage.feature import hog\n\ndef hog_images(crop):    \n    image=crop[:,:,1]    \n    fd, hog_image = hog(image, orientations=8, pixels_per_cell=(4, 4),cells_per_block=(2, 2), visualize=True)    \n    return hog_image\n\na = img_cov_path.split('/')[-2]\nb = img_jmi_path.split('/')[-2]\nc = img_juni_path.split('/')[-2]\nd = img_uerd_path.split('/')[-2]\nim = cv2.imread(img_cov_path)\nhog_image = hog_images(im)\nplt.imshow(hog_image)\n\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(141)\nim = cv2.imread(img_cov_path)\nhog_image = hog_images(im)\ndiffed_imgs_plt(hog_image,hog_image)\nplt.title('Pixel differe b/w ' + a + '/' + a)\n\nplt.subplot(142)\nim1 = cv2.imread(img_juni_path)\nhog_image1 = hog_images(im1)\nim1 = subtract_median_bg_image(im1)\ndiffed_imgs_plt(hog_image,hog_image1)\nplt.title('Pixel differe b/w ' + a + '/' + b)\n\nplt.subplot(143)\nim2 = cv2.imread(img_jmi_path)\nhog_image2 = hog_images(im2)\ndiffed_imgs_plt(hog_image,hog_image2)\nplt.title('Pixel differe b/w ' + a + '/' + c)\n\nplt.subplot(144)\nim3 = cv2.imread(img_uerd_path)\nhog_image3 = hog_images(im3)\ndiffed_imgs_plt(hog_image,hog_image3)\nplt.title('Pixel differe b/w ' + a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Tan_inv(crop):    \n    gre=crop[:,:,1].astype(np.float64)    \n    red=crop[:,:,2].astype(np.float64)        \n    red[red==0]=0.000001    \n    m=gre/red   \n    n=np.arctan(m) \n    ij=(n*255)/3.14    \n    j=ij.astype(np.uint8)    \n    equ = cv2.equalizeHist(j)    \n    return equ\n\n\na = img_cov_path.split('/')[-2]\nb = img_jmi_path.split('/')[-2]\nc = img_juni_path.split('/')[-2]\nd = img_uerd_path.split('/')[-2]\nim = cv2.imread(img_cov_path)\nTan_inv1 = Tan_inv(im)\nplt.imshow(Tan_inv1)\n\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(141)\nim = cv2.imread(img_cov_path)\nTan_inv1 = Tan_inv(im)\ndiffed_imgs_plt(Tan_inv1,Tan_inv1)\nplt.title('Pixel differe b/w ' + a + '/' + a)\n\nplt.subplot(142)\nim1 = cv2.imread(img_juni_path)\nTan_inv2 = Tan_inv(im1)\ndiffed_imgs_plt(Tan_inv1,Tan_inv2)\nplt.title('Pixel differe b/w ' + a + '/' + b)\n\nplt.subplot(143)\nim2 = cv2.imread(img_jmi_path)\nTan_inv3 = Tan_inv(im2)\ndiffed_imgs_plt(Tan_inv1,Tan_inv3)\nplt.title('Pixel differe b/w ' + a + '/' + c)\n\nplt.subplot(144)\nim3 = cv2.imread(img_uerd_path)\nTan_inv4 = Tan_inv(im3)\ndiffed_imgs_plt(Tan_inv1,Tan_inv4)\nplt.title('Pixel differe b/w ' + a + '/' + d)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Tan_inv function does not perform as well as the other functions as it does not signifies much difference between the images and stegnography images","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"**FFT(Fourier Transform)** - fft decomposes an image into its real and imaginary components which is a representation of the image in the frequency domain. If the input signal is an image then the number of frequencies in the frequency domain is equal to the number of pixels in the image or spatial domain. The inverse transform re-transforms the frequencies to the image in the spatial domain.The Fourier Transform is used in a wide range of applications, such as image analysis, image filtering, image reconstruction and image compression.But why we use this fft .Image has changes in brighness level according to picture. The brightness changes in rows and columns. We can consider brightness level in a row as a discrete signal 1D and we can apply DFT. same way DFT is applied for each row or column and corresponding DFT row or column is generated.So through this we can analyze the changes in the brightness between the non stegno and stegno images\n![](https://www.clear.rice.edu/elec301/Projects01/image_filt/matlab/spectrum.gif)\n![](data:image/png;base64,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)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"img = cv2.imread(img_cov_path,0)\nf = np.fft.fft2(img)\nfshift = np.fft.fftshift(f)\nrows, cols = img.shape\ncrow,ccol = int(rows/2) , int(cols/2)\nfshift[crow-30:crow+30, ccol-30:ccol+30] = 0\nf_ishift = np.fft.ifftshift(fshift)\nimg_back = np.fft.ifft2(f_ishift)\nimg_back = np.abs(img_back)\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(131)\nplt.imshow(img, cmap = 'gray')\nplt.title('cover Input Image')\nplt.subplot(132)\nplt.imshow(img_back, cmap = 'gray')\nplt.title('cover image with absolute fft values')\nplt.subplot(133)\nplt.imshow(img_back)\nplt.title('cover image after fft ')\n\n\nimg = cv2.imread(img_juni_path,0)\nf = np.fft.fft2(img)\nfshift = np.fft.fftshift(f)\nrows, cols = img.shape\ncrow,ccol = int(rows/2) , int(cols/2)\nfshift[crow-30:crow+30, ccol-30:ccol+30] = 0\nf_ishift = np.fft.ifftshift(fshift)\nimg_back = np.fft.ifft2(f_ishift)\nimg_back = np.abs(img_back)\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(131)\nplt.imshow(img, cmap = 'gray')\nplt.title('juni Input Image')\nplt.subplot(132)\nplt.imshow(img_back, cmap = 'gray')\nplt.title('juni image with absolute fft values')\nplt.subplot(133)\nplt.imshow(img_back)\nplt.title('juni image after fft ')\n\n\nimg = cv2.imread(img_jmi_path,0)\nf = np.fft.fft2(img)\nfshift = np.fft.fftshift(f)\nrows, cols = img.shape\ncrow,ccol = int(rows/2) , int(cols/2)\nfshift[crow-30:crow+30, ccol-30:ccol+30] = 0\nf_ishift = np.fft.ifftshift(fshift)\nimg_back = np.fft.ifft2(f_ishift)\nimg_back = np.abs(img_back)\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(131)\nplt.imshow(img, cmap = 'gray')\nplt.title('jmi Input Image')\nplt.subplot(132)\nplt.imshow(img_back, cmap = 'gray')\nplt.title('jmi image with absolute fft values')\nplt.subplot(133)\nplt.imshow(img_back)\nplt.title('jmi image after fft ')\n\nimg = cv2.imread(img_uerd_path,0)\nf = np.fft.fft2(img)\nfshift = np.fft.fftshift(f)\nrows, cols = img.shape\ncrow,ccol = int(rows/2) , int(cols/2)\nfshift[crow-30:crow+30, ccol-30:ccol+30] = 0\nf_ishift = np.fft.ifftshift(fshift)\nimg_back = np.fft.ifft2(f_ishift)\nimg_back = np.abs(img_back)\nfig, ax = plt.subplots(figsize=(20, 5))\nplt.subplot(131)\nplt.imshow(img, cmap = 'gray')\nplt.title('uerd Input Image')\nplt.subplot(132)\nplt.imshow(img_back, cmap = 'gray')\nplt.title('uerd image with absolute fft values')\nplt.subplot(133)\nplt.imshow(img_back)\nplt.title('uerd image after fft ')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Though we can see the difference with naked eye but lets analyze the difference between the cover fft and stegno fft images","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from numpy.fft import fft2\nfrom numpy import r_\ndef show_dct_bgr(img_num):\n    # Let us plot image histogram for cover and stego images in Gray scale:\n    fig, ax = plt.subplots(figsize=(20, 10))\n    print(f\"{path}/{folders[0]}/0000{img_num}.jpg\")\n    img_cov = cv2.imread(f\"{path}/{folders[0]}/0000{img_num}.jpg\", -1)\n    img_jmi = cv2.imread(f\"{path}/{folders[1]}/0000{img_num}.jpg\", -1)\n    img_juni = cv2.imread(f\"{path}/{folders[2]}/0000{img_num}.jpg\", -1)\n    img_uerd = cv2.imread(f\"{path}/{folders[3]}/0000{img_num}.jpg\", -1)\n    \n    imsize = img_cov.shape\n    \n    fft_cov = np.zeros(imsize)\n    fft_jmi = np.zeros(imsize)\n    fft_juni = np.zeros(imsize)\n    fft_uerd = np.zeros(imsize) \n    \n    for i in r_[:imsize[0]:4]:\n        for j in r_[:imsize[1]:4]:\n            fft_cov[:,:,0] [i:(i+4),j:(j+4)] = fft2( img_cov[:,:,0][i:(i+4),j:(j+4)] )\n            fft_jmi[:,:,0] [i:(i+4),j:(j+4)] = fft2( img_jmi[:,:,0][i:(i+4),j:(j+4)] )\n            fft_juni[:,:,0][i:(i+4),j:(j+4)] = fft2( img_juni[:,:,0][i:(i+4),j:(j+4)] )\n            fft_uerd[:,:,0][i:(i+4),j:(j+4)] = fft2( img_uerd[:,:,0][i:(i+4),j:(j+4)] )\n\n            fft_cov[:,:,1][i:(i+4),j:(j+4)] = fft2( img_cov[:,:,1][i:(i+4),j:(j+4)] )\n            fft_jmi[:,:,1][i:(i+4),j:(j+4)] = fft2( img_jmi[:,:,1][i:(i+4),j:(j+4)] )\n            fft_juni[:,:,1][i:(i+4),j:(j+4)] = fft2( img_juni[:,:,1][i:(i+4),j:(j+4)] )\n            fft_uerd[:,:,1][i:(i+4),j:(j+4)] = fft2( img_uerd[:,:,1][i:(i+4),j:(j+4)] )\n            \n            fft_cov[:,:,2][i:(i+4),j:(j+4)] = fft2( img_cov[:,:,2][i:(i+4),j:(j+4)] )\n            fft_jmi[:,:,2][i:(i+4),j:(j+4)] = fft2( img_jmi[:,:,2][i:(i+4),j:(j+4)] )\n            fft_juni[:,:,2][i:(i+4),j:(j+4)] = fft2( img_juni[:,:,2][i:(i+4),j:(j+4)] )\n            fft_uerd[:,:,2][i:(i+4),j:(j+4)] = fft2( img_uerd[:,:,2][i:(i+4),j:(j+4)] )\n \n   #################################\n\n    plt.subplot(141)\n    plt.title(\"Cover\")\n    plt.imshow(img_cov)\n\n    plt.subplot(142)\n    plt.title(\"JMiPOD\")\n    plt.imshow(img_jmi)\n\n    plt.subplot(143)\n    plt.title(\"JUNIWARD\")\n    plt.imshow(img_juni)\n\n    plt.subplot(144)\n    plt.title(\"UERD\")\n    plt.imshow(img_uerd)\n\n    plt.show()    \n  \n\n    #################################\n    fig, ax = plt.subplots(figsize=(20, 10))\n    plt.subplot(141)\n    plt.title(\"ffT on Cover\")\n    plt.imshow(fft_cov)\n\n    plt.subplot(142)\n    plt.title(\"ffT on JMiPOD\")\n    plt.imshow(fft_jmi)\n\n    plt.subplot(143)\n    plt.title(\"ffT on JUNIWARD\")\n    plt.imshow(fft_juni)\n\n    plt.subplot(144)\n    plt.title(\"ffT on UERD\")\n    plt.imshow(fft_uerd)\n\n    plt.show()\n \n    #########################################\n    \n    diff_cov_jmi = fft_cov - fft_jmi\n    diff_cov_juni = fft_cov - fft_juni\n    diff_cov_uerd = fft_cov - fft_uerd\n    ########################################\n    \n    fig, ax = plt.subplots(figsize=(20, 10))\n    plt.subplot(141)\n    plt.title(\"ffT Cover\")\n    plt.imshow(fft_cov)\n\n    plt.subplot(142)\n    plt.title(\"ffT Cover - ffT JMiPOD\")\n    plt.imshow(diff_cov_jmi)\n\n    plt.subplot(143)\n    plt.title(\"ffT Cover - ffT JUNIWARD\")\n    plt.imshow(diff_cov_juni)\n\n    plt.subplot(144)\n    plt.title(\"ffT Cover - ffT UERD\")\n    plt.imshow(diff_cov_uerd)\n\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dct_bgr(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Sober** - Edges in images are areas with strong intensity contrasts; a jump in intensity from one pixel to the next. The process of edge detection significantly reduces the amount of data and filters out uneeded information, while preserving the important structural properties of an image. This algorithms has 2 filters\n![](https://automaticaddison.com/wp-content/uploads/2019/12/11-x-y-direction-kernel.jpg)these filter are then convolved over the image and than sumed<br>\nGx = x-direction kernel * (3×3 portion of image A with (x,y) as the center cell)<br>\nGy = y-direction kernel * (3×3 portion of image A with (x,y) as the center cell)<br>\nmagnitude(G) = square_root(Gx2 + Gy2)<br>\nThe direction of the gradient Ɵ at pixel (x, y) is: Ɵ = atan(Gy / Gx)<br>\n\n**Laplacian** - \nTo understand the laplacian filter we assume that we have a graph of the intensity values for each pixel in an image, the Sobelfilter takes the derivative if the intensity is at ist maxima than we can have a edge in the region.One limitation with the approach above is that the first derivative of an image might be subject to a lot of noise. Local peaks in the slope of the intensity values might be due to shadows or tiny color changes that are not edges at all. So this might lead us to get the edges but we will also have some noise as classified edges so an alternative to use is to take first derivative of an image and then second derivative, \nAn edge occurs where the graph of the second derivative crosses zero. This second derivative-based method is called the Laplacian algorithm. \nWe also set a threshold value to distinguish noise from edges. If the second derivative magnitude at a pixel exceeds this threshold, the pixel is part of an edge.\n![](https://automaticaddison.com/wp-content/uploads/2019/12/5-log.jpg)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport numpy as np\nfrom matplotlib import pyplot as plt\n\nimg = cv2.imread(img_cov_path,-1)\n\nlaplacian = cv2.Laplacian(img,cv2.CV_64F)\nsobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)\n\nimg1 = cv2.imread(img_jmi_path,-1)\n\nlaplacian1 = cv2.Laplacian(img1,cv2.CV_64F)\nsobelx1 = cv2.Sobel(img1,cv2.CV_64F,1,0,ksize=5)\nfig, ax = plt.subplots(figsize=(20, 10))\nplt.subplot(2,3,1),plt.imshow(img-img1,cmap = 'gray')\nplt.title('Original pix diff jmi'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,2),plt.imshow(laplacian-laplacian1,cmap = 'gray')\nplt.title('Laplacian pix diff jmi'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,3),plt.imshow(sobelx-sobelx1,cmap = 'gray')\nplt.title('SobelX pix diff jmi'), plt.xticks([]), plt.yticks([])\nplt.show()\n\nimg2 = cv2.imread(img_juni_path,-1)\n\nlaplacian2 = cv2.Laplacian(img2,cv2.CV_64F)\nsobelx2 = cv2.Sobel(img2,cv2.CV_64F,1,0,ksize=5)\nfig, ax = plt.subplots(figsize=(20, 10))\nplt.subplot(2,3,1),plt.imshow(img-img2,cmap = 'gray')\nplt.title('Original pix diff juni'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,2),plt.imshow(laplacian-laplacian2,cmap = 'gray')\nplt.title('Laplacian pix diff juni'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,3),plt.imshow(sobelx-sobelx2,cmap = 'gray')\nplt.title('SobelX pix diff juni'), plt.xticks([]), plt.yticks([])\nplt.show()\n\n\nimg3 = cv2.imread(img_uerd_path,-1)\n\nlaplacian3 = cv2.Laplacian(img3,cv2.CV_64F)\nsobelx3 = cv2.Sobel(img3,cv2.CV_64F,1,0,ksize=5)\nfig, ax = plt.subplots(figsize=(20, 10))\nplt.subplot(2,3,1),plt.imshow(img-img3,cmap = 'gray')\nplt.title('Original pix diff uerd'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,2),plt.imshow(laplacian-laplacian3,cmap = 'gray')\nplt.title('Laplacian pix diff uerd'), plt.xticks([]), plt.yticks([])\nplt.subplot(2,3,3),plt.imshow(sobelx-sobelx3,cmap = 'gray')\nplt.title('Sobel X pix diff uerd'), plt.xticks([]), plt.yticks([])\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Local binary patterns** <br>\n\n(LBP) is a type of visual descriptor used for classification in computer vision. LBP is the particular case of the Texture Spectrum model  LBP was first described in 1994.It has since been found to be a powerful feature for texture classification; it has further been determined that when LBP is combined with the Histogram of oriented gradients (HOG) descriptor, it improves the detection performance considerably on some datasets.A comparison of several improvements of the original LBP in the field of background subtraction was made in 2015 by Silva et al. A full survey of the different versions of LBP can be found in Bouwmans et al.<br>\n\n![](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1*vBddGyANCoj4PYiKNptXnQ.png&f=1&nofb=1)\n\ncode insperation - https://www.pyimagesearch.com/2015/12/07/local-binary-patterns-with-python-opencv/","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# import the necessary packages\nfrom skimage import feature\n\ndef LocalBinaryPatterns(image1_path,image2_path,image3_path,image4_path):\n    p,r = 8,1\n    fig, ax = plt.subplots(figsize=(20, 10))\n    img_cov = cv2.imread(image1_path, -1)\n    gray_cov = cv2.cvtColor(img_cov, cv2.COLOR_BGR2GRAY)\n    ldp = feature.local_binary_pattern(gray_cov, p,\n            r, method=\"uniform\")\n    plt.subplot(141)\n    diffed_imgs_plt(ldp,ldp)\n    plt.title('Pixel differe b/w ' + a + '/' + a)\n    \n    \n    img_jmi = cv2.imread(image2_path, -1)\n    gray_val = cv2.cvtColor(img_jmi, cv2.COLOR_BGR2GRAY)\n    ldp2 = feature.local_binary_pattern(gray_val, p,\n            r, method=\"uniform\")\n    plt.subplot(142)\n    diffed_imgs_plt(ldp,ldp2)\n    plt.title('Pixel differe b/w ' + a + '/' + b)\n    \n    \n    img_juni = cv2.imread(image3_path, -1)\n    gray_val = cv2.cvtColor(img_juni, cv2.COLOR_BGR2GRAY)\n    ldp3 = feature.local_binary_pattern(gray_val, p,\n            r, method=\"uniform\")\n    plt.subplot(143)\n    diffed_imgs_plt(ldp,ldp3)\n    plt.title('Pixel differe b/w ' + a + '/' + c)\n    \n    \n    img_uerd = cv2.imread(image4_path, -1)\n    gray_val = cv2.cvtColor(img_uerd, cv2.COLOR_BGR2GRAY)\n    ldp4 = feature.local_binary_pattern(gray_val, p,\n            r, method=\"uniform\")\n    plt.subplot(144)\n    diffed_imgs_plt(ldp,ldp4)\n    plt.title('Pixel differe b/w ' + a + '/' + d)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"LocalBinaryPatterns(img_cov_path,img_jmi_path,img_juni_path,img_uerd_path)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Whats Next\n\n1. So you might apply any of these filter to the notebooks as an augmentation this might add a new direction in training\n2. Shows how do these filters could find ther underlying features so what you can do is to stack them each other\n3. Your can upvote ;-))","execution_count":null}],"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}