{"cells":[
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport zipfile\nimport os\nimport io\nfrom PIL import Image, ImageDraw\nimport datetime\nimport random\nimport cv2\nfrom matplotlib.pyplot import imshow"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# Original function, using PIL module\ndef dhash(image,hash_size = 16):\n    image = image.convert('LA').resize((hash_size+1,hash_size),Image.ANTIALIAS)\n    difference = []\n    for row in range(hash_size):\n        for col in range(hash_size):\n            pixel_left = image.getpixel((col,row))\n            pixel_right = image.getpixel((col+1,row))\n            difference.append(pixel_left>pixel_right)\n    decimal_value = 0\n    hex_string = []\n    for index, value in enumerate(difference):\n        if value:\n            decimal_value += 2**(index%8)\n        if (index%8) == 7:\n            hex_string.append(hex(decimal_value)[2:].rjust(2,'0'))\n            decimal_value = 0\n    \n    return ''.join(hex_string)"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# 4x faster function, using cv2 module and some numpy tricks\ndef dhash_cv2(im, hash_size = 16):\n    # Convert to grayscale\n    imz = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)\n\n    # Resize\n    px = cv2.resize(imz, (hash_size+1,hash_size), interpolation=cv2.INTER_AREA)\n\n    # Calculate difference between adjacent pixels\n    diff = (px[:,:-1]>px[:,1:]).ravel()\n    # Create hex string from every 8 bits. Steps:\n    # 'difference.reshape(-1, 8)' -> Group every 8 booleans\n    # 'np.where(x)[0]'            -> Convert an array of booleans to index values.\n    #                                [False, True, True, False, True] becames [1, 2, 4]\n    # '(1 << x).sum()'            -> Faster version of sum(2**x)\n    #                                [1, 2, 4] -> [1**2, 2**2, 4**2] -> [1, 4, 16] -> 21\n    # '\"%0.2x\" % x'               -> Convert integer to hex string (21 -> '15')\n    hex_string = map(lambda x: \"%0.2x\" % (1 << np.where(x)[0]).sum(), diff.reshape(-1, 8))\n    \n\n    # Join hex string array\n    return ''.join(hex_string)"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# Generate a fake image (.zip files are not available for Kernels)\ndef drawImage():\n    testImage = Image.new(\"RGB\", (600,600), (255,255,255))\n    draw = ImageDraw.Draw(testImage)\n    for r in range(50):\n        x = random.randrange(0, 500)\n        y = random.randrange(0, 500)\n        h = random.randrange(20, 100)\n        w = random.randrange(20, 100)\n        r = random.randrange(0,255)\n        g = random.randrange(0,255)\n        b = random.randrange(0,255)\n        \n        draw.rectangle(((x,y),(x+w,y+h)), fill=(r, g, b))\n        \n    del draw\n    return testImage\n\n# PIL instance\nimg = drawImage()\n\n# Numpy instance\nimg_np = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)\n\n%matplotlib inline\nimshow(np.asarray(img))"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# Generate hashes\n\nhash1 = dhash(img)\nhash2 = dhash_cv2(img_np)\n\n# NOTICE THAT BOTH ARE DIFFERENT! In my debug of what caused this difference, I noticed that is due to \n# different resize functions. However, I plotted the 'difference' bool array of both methods and can\n# assure that they are very close\nprint(hash1, hash2)"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# Performance of previous function\n%timeit dhash(img)"
 },
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "# Performance of cv2 version (4x speedup!)\n%timeit dhash_cv2(img_np)"
 }
],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"}}, "nbformat": 4, "nbformat_minor": 0}