{"cells":[{"metadata":{},"cell_type":"markdown","source":"DISCLAIMER\n===========\nUse at your own risk, this is not an acceptable approach per the competition rules. Posted for continued learning only.  For explanation on why it works check out [@cdeotte](https://www.kaggle.com/cdeotte) great [kernel](https://www.kaggle.com/cdeotte/supervised-generative-dog-net) \n\nTranslations and comments by [@takumiito](https://www.kaggle.com/takumiito) and [@timdarcet](https://www.kaggle.com/timdarcet)"},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":false},"cell_type":"code","source":"from PIL import Image, ImageStat, ImageEnhance\nfrom multiprocessing import Pool, cpu_count\nimport glob, zipfile, os, itertools\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom sklearn import *\nimport pandas as pd\nimport numpy as np\nimport scipy, cv2\nimport imagehash\n\n# 統計データを取得\n# Get statistical data\ndef get_features(path):\n    try:\n        st = []\n        # 画像のpixcelデータを取得\n        # Get pixel data of image\n        img = Image.open(path)\n        img = img.resize((100,int(img.size[1]/(img.size[0]/100))), Image.ANTIALIAS)\n        img = img.crop((0, 0, 64, 64))\n        # 画像のpixcelデータのRGB別の統計結果を開始\n        # Start statistics by RGB of pixcel data of image\n        im_stats_ = ImageStat.Stat(img)\n        # 合計\n        # total\n        st += im_stats_.sum\n        # 平均値\n        # Average value\n        st += im_stats_.mean\n        # 二乗平均平方根\n        # Root mean square\n        st += im_stats_.rms\n        # 分散\n        # dispersion\n        st += im_stats_.var\n        # 標準偏差\n        # standard deviation\n        st += im_stats_.stddev\n        img = np.array(img)\n        m, s = cv2.meanStdDev(img)\n        st += list(m)\n        st += list(s)\n        st += [cv2.Laplacian(img, cv2.CV_64F).var()]\n        st += [cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5).var()]\n        st += [cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5).var()]\n        img = img[:,:,:3]\n        st += [scipy.stats.kurtosis(img[:,:,0].ravel())]\n        st += [scipy.stats.kurtosis(img[:,:,1].ravel())]\n        st += [scipy.stats.kurtosis(img[:,:,2].ravel())]\n        st += [scipy.stats.skew(img[:,:,0].ravel())]\n        st += [scipy.stats.skew(img[:,:,1].ravel())]\n        st += [scipy.stats.skew(img[:,:,2].ravel())]\n    except:\n        print(path)\n    return [path, st]\n\n# 並列処理\n# Parallel processing\ndef normalize_img(paths):\n    imf_d = {}\n    p = Pool(cpu_count())\n    # get_features関数を並列処理\n    # Parallelize get_features function\n    ret = p.map(get_features, paths)\n    # 並列処理の結果を配列化\n    # Arrange the result of parallel processing\n    for i in range(len(ret)):\n        imf_d[ret[i][0]] = ret[i][1]\n    ret = []\n    fdata = [imf_d[f] for f in paths]\n    return pd.DataFrame(fdata)\n\n# 画像データのパスを読み込み\n# Load path of image data\ndog_bytes = pd.DataFrame(glob.glob('../input/all-dogs/all-dogs/**'), columns=['Path'])\n# 画像毎にpixcelデータの統計データを取得\n# Get statistical data of pixcel data for each image\ndog_bytes = pd.concat((dog_bytes, normalize_img(dog_bytes.Path.values)), axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels = pd.DataFrame(glob.glob('../input/annotation/Annotation/**/**'), columns=['Path'])\nlabels['Labels'] = labels['Path'].map(lambda x: x.split('/')[4].split('-')[1])\nlabels['FileName'] = labels['Path'].map(lambda x: x.split('/')[-1] + '.jpg')\nlabels = {f:l for f,l in labels[['FileName', 'Labels']].values}\n\ndog_bytes['FileName'] = dog_bytes['Path'].map(lambda x: x.split('/')[-1])\ndog_bytes['Labels'] = dog_bytes['FileName'].map(labels)\ndog_bytes.head()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"code","source":"# KMeans法によって、画像データを100分類に分割\n# Divide image data into 100 classifications by KMeans method\ndog_bytes['Group'] = cluster.KMeans(n_clusters=400, random_state=4, n_jobs=-1).fit_predict(dog_bytes[list(range(30))])\n# 100分類から数が多い5分類を取得（表示）\n#  Get 5 classifications with many from 400 classifications (display)\ndog_bytes['Group'].value_counts()[:5]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Inspiration\n==========="},{"metadata":{"trusted":false},"cell_type":"code","source":"# 画像を表示するwindowを生成\n# 単位はインチ\n# Generate a window to display the image\n# Unit is in inches\nfig = plt.figure(figsize=(8, 80))\nsamples = []\n# 特定の分類の画像データから5つずつサンプルを取得\n# Get 5 samples from image data of specific classification\nfor i in range(400):\n    # 特定の分類の画像データを取得\n    # Get image data of a specific classification\n    g = dog_bytes[dog_bytes['Group'] == i]\n    if len(g) > 5:\n        # 特定の分類の画像データから5つのサンプルを取得\n        # Get 5 samples from image data of specific classification\n        samples += list(g['Path'].values[:5])\n\n# 分類毎の画像を表示\n# Display images by classification\nfor i in range(len(samples))[:50]:\n    # 5行5列分のwindowの内、一つを取得\n    # Get one of the 5 rows and 5 columns of windows\n    ax = fig.add_subplot(len(samples)/5, 5, i+1, xticks=[], yticks=[])\n    # 画像データを取得\n    # Get image data\n    img = Image.open(samples[i])\n    # 画像データをリサイズ\n    # 単位はpixel\n    # 解像度(dpi) = pixel / インチ\n    # Resize image data\n    # Unit is pixel\n    # Resolution (dpi) = pixel / inch\n    img = img.resize((100,int(img.size[1]/(img.size[0]/100))), Image.ANTIALIAS)\n    img = img.crop((0, 0, 64, 64))\n    plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Motivation\n=============="},{"metadata":{"trusted":false},"cell_type":"code","source":"def sim_img(path):\n    img = Image.open(path).convert('RGB')\n    img = img.resize((100,int(img.size[1]/(img.size[0]/100))), Image.ANTIALIAS)\n    img = img.crop((0, 0, 64, 64))\n    return img\n\nsamples = []\nfor i in range(400):\n    g = dog_bytes[dog_bytes['Group'] == i]\n    p = g['Path'].values\n    for i in range(0,len(p)-2, 2):\n        samples.append([p[i],p[i+1]])\n    if len(samples) > 11_000: break\nfor i in range(0,len(samples)-1):\n    samples.append([samples[i][0],samples[i+1][0]])\n    if len(samples) > 11_000: break\nprint(len(samples))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Submission\n============="},{"metadata":{"trusted":false},"cell_type":"code","source":"z = zipfile.PyZipFile('images.zip', mode='w')\nfor i in range(10_000):\n    p1, p2 = samples[i]\n    # 同じ分類内の２つの画像を混合し、新しい画像を作成\n    # Mix two images in the same category and create a new image\n    # out = p1 * (1 - 0.01) + p2 * 0.01\n    im = Image.blend(sim_img(p1), sim_img(p2), alpha=0.01)\n    f = str(i)+'.png'\n    im.save(f,'PNG'); z.write(f); os.remove(f)\n    if i % 1000==0:\n        print(i)\nprint (len(z.namelist()))\nz.close()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Lets spin some more ML in to this\n==============================="},{"metadata":{"trusted":false},"cell_type":"code","source":"d = ensemble.RandomForestClassifier(n_jobs=-1, n_estimators=400, random_state=3)\n\ngroups = dog_bytes['Group'].value_counts().index[:100]\ndog_bytes['Original'] = dog_bytes['Group'].map(lambda x: 0 if x in groups else 1) #target label\n\n#Lets create test set\ng = dog_bytes[dog_bytes['Group'].isin(groups)]\ns = list([p for p,_ in itertools.groupby(sorted([sorted(p) for p in list(itertools.permutations(g['Path'].values[:60], 2))]))])\ntest = pd.DataFrame(s, columns=['Path1', 'Path2'])\ntest['Image'] = test.index.map(lambda x: 'test/' + str(x) + '.png')\nos.mkdir('test/')\nfor i in range(len(test)):\n    im = Image.blend(sim_img(test.Path1[i]), sim_img(test.Path2[i]), alpha=0.5)\n    im.save(test['Image'][i],'PNG')\ntest = pd.concat((test, normalize_img(test.Image.values)), axis=1)\n\nd.fit(dog_bytes[list(range(30))], dog_bytes['Original'])\ntest['Original'] = d.predict_proba(test[list(range(30))])[:,1]\ntest = test.sort_values(by=['Original'], ascending=False).reset_index(drop=True)\ndog_bytes.Original.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"fig = plt.figure(figsize=(4, 20))\nfor i in range(10):\n    ax = fig.add_subplot(10, 3, (3*i)+1, xticks=[], yticks=[])\n    plt.imshow(Image.open(test.Path1[i]).resize((100,int(img.size[1]/(img.size[0]/100))), Image.ANTIALIAS))\n    ax = fig.add_subplot(10, 3, (3*i)+2, xticks=[], yticks=[])\n    plt.imshow(Image.open(test.Path2[i]).resize((100,int(img.size[1]/(img.size[0]/100))), Image.ANTIALIAS))\n    ax = fig.add_subplot(10, 3, (3*i)+3, xticks=[], yticks=[])\n    plt.imshow(Image.open(test.Image[i]))\nimport shutil; shutil.rmtree('test/')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ｈ𝐀𝑷𝑷𝓎 🇰𝗮𝘨𝘨🇱𝖎Ｎɢ  💯\n===================="}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.8"}},"nbformat":4,"nbformat_minor":1}