{"cells":[{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","collapsed":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"markdown","source":"Reference\n\n- Awesome Kernel, thanks @martinpiotte : https://www.kaggle.com/martinpiotte/bounding-box-model\n- cropping.model: https://www.kaggle.com/martinpiotte/bounding-box-model/output\n- Data: https://www.kaggle.com/c/humpback-whale-identification/data"},{"metadata":{"trusted":true,"_uuid":"53e265d56719498b6c971b5cf8ac4c5b727bbd19"},"cell_type":"code","source":"import os\n\nimport PIL\nfrom PIL import Image\nfrom PIL.ImageDraw import Draw\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom keras.models import load_model\nfrom keras.preprocessing import image\nfrom keras.preprocessing.image import img_to_array\nfrom scipy.ndimage import affine_transform\nfrom keras import backend as K\n\nimport pandas as pd\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4a432aea33948e321cf25617d67928097df0c317"},"cell_type":"code","source":"MODEL_BASE = '../input/bounding-box-model'\nDATA = '../input/humpback-whale-identification'\nTRAIN = os.path.join(DATA, 'train')\nTEST = os.path.join(DATA, 'test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6a7af444edd754740b2beb1fe32116a3aae6035c"},"cell_type":"code","source":"model = load_model(os.path.join(MODEL_BASE, 'cropping.model'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3b03b5b50d2c4787d9d6c065a160316ddecd45fc"},"cell_type":"code","source":"train_paths = [img for img in os.listdir(TRAIN)]\ntest_paths = [img for img in os.listdir(TEST)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0b45eea2cd93933ea852d08a30c846440eeb6376"},"cell_type":"code","source":"from PIL import Image as pil_image\n\n# Define useful constants\nimg_shape  = (128,128,1)\nanisotropy = 2.15\n\ndef center_transform(affine, input_shape):\n    hi, wi = float(input_shape[0]), float(input_shape[1])\n    ho, wo = float(img_shape[0]), float(img_shape[1])\n    top, left, bottom, right = 0, 0, hi, wi\n    if wi/hi/anisotropy < wo/ho: # input image too narrow, extend width\n        w     = hi*wo/ho*anisotropy\n        left  = (wi-w)/2\n        right = left + w\n    else: # input image too wide, extend height\n        h      = wi*ho/wo/anisotropy\n        top    = (hi-h)/2\n        bottom = top + h\n    center_matrix   = np.array([[1, 0, -ho/2], [0, 1, -wo/2], [0, 0, 1]])\n    scale_matrix    = np.array([[(bottom - top)/ho, 0, 0], [0, (right - left)/wo, 0], [0, 0, 1]])\n    decenter_matrix = np.array([[1, 0, hi/2], [0, 1, wi/2], [0, 0, 1]])\n    return np.dot(np.dot(decenter_matrix, scale_matrix), np.dot(affine, center_matrix))\n\n# Apply an affine transformation to an image represented as a numpy array.\ndef transform_img(x, affine):\n    matrix   = affine[:2,:2]\n    offset   = affine[:2,2]\n    x        = np.moveaxis(x, -1, 0)\n    channels = [affine_transform(channel, matrix, offset, output_shape=img_shape[:-1], order=1,\n                                 mode='constant', cval=np.average(channel)) for channel in x]\n    return np.moveaxis(np.stack(channels, axis=0), 0, -1)\n\ndef read_raw_image(p):\n    return pil_image.open(p)\n\ndef read_for_validation(x):\n    t  = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])\n    t  = center_transform(t, x.shape)\n    x  = transform_img(x, t)\n    x -= np.mean(x, keepdims=True)\n    x /= np.std(x, keepdims=True) + K.epsilon()\n    return x, t\n\ndef coord_transform(list, trans):\n    result = []\n    for x,y in list:\n        y,x,_ = trans.dot([y,x,1]).astype(np.int)\n        result.append((x,y))\n    return result\n\ndef read_array(p):\n    img = read_raw_image(p).convert('L')\n    return img_to_array(img)\n\ndef make_bbox(p):\n    raw = read_array(p)\n    width, height = raw.shape[1], raw.shape[0]\n    img,trans         = read_for_validation(raw)\n    a                 = np.expand_dims(img, axis=0)\n    x0, y0, x1, y1    = model.predict(a).squeeze()\n    (u0, v0),(u1, v1) = coord_transform([(x0,y0),(x1,y1)], trans)\n    bbox = [max(u0,0), max(v0,0), min(u1,width), min(v1,height)]\n    if bbox[0] >= bbox[2] or bbox[1] >= bbox[3]:\n        bbox = [0,0,width,height]\n    return bbox","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6bbddf36e5cbc397e7baa1b87635063f6da8cbef"},"cell_type":"code","source":"bbox_df = pd.DataFrame(columns=['Image','x0','y0','x1','y1']).set_index('Image')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"36085d38dc2767f034317bfb05e587d386e137dd"},"cell_type":"code","source":"for img in tqdm(train_paths):\n    bbox_df.loc[img] = make_bbox(os.path.join(TRAIN,img))\n    \nfor img in tqdm(test_paths):\n    bbox_df.loc[img] = make_bbox(os.path.join(TEST,img))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d9b9cfb37ddb3f0699a1fb37862b988bead01a1a"},"cell_type":"code","source":"bbox_df.to_csv(\"bounding_boxes.csv\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}