{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport os\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6747a3277eedb9ce3fc8c63bc77ee612ad952b01"},"cell_type":"code","source":"DATA = '../input'\nLABELS='train.csv'\nTRAIN = os.path.join(DATA, 'train')\nTEST = os.path.join(DATA, 'test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"035adc8faf7e7290652c611616b1537af9ad0715"},"cell_type":"code","source":"train_paths = [os.path.join(TRAIN,img) for img in os.listdir(TRAIN)]\ntest_paths = [os.path.join(TEST,img) for img in os.listdir(TEST)]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b71ddc4a77a3547e72ae272804c83065d98a1022"},"cell_type":"markdown","source":"# Generate cropping method"},{"metadata":{"_uuid":"da044b8967af6fed3dd7920f4b75304630e3a234"},"cell_type":"markdown","source":"## step 1: edge detection"},{"metadata":{"_uuid":"3d8f0fb1f220ec5a608af5e5f5c26540c17995f2"},"cell_type":"markdown","source":"applay gaussian filter on image"},{"metadata":{"trusted":true,"_uuid":"600302fcf470c14909c836b15c46b1dd3f7defac"},"cell_type":"code","source":"import cv2\n#read image\nimg=cv2.imread(train_paths[5])\nblurred = cv2.GaussianBlur(img, (7,7), 0) # Remove noise\nplt.imshow(blurred)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3f67a0b46bd7950e4286e2ff1f79454ddb0870b1"},"cell_type":"markdown","source":"Erossion: A kernel(a matrix of odd size(3,5,7) is convolved with the image.  \nA pixel in the original image (either 1 or 0) will be considered 1 only if all the pixels under the kernel is 1, otherwise it is eroded (made to zero).  \nThus all the pixels near boundary will be discarded depending upon the size of kernel.  \nSo the thickness or size of the foreground object decreases or simply white region decreases in the image.  "},{"metadata":{"trusted":true,"_uuid":"7df69541100c00b7d4b2be156c89a3a0c1ee3848"},"cell_type":"code","source":"#close the small line gaps using errosion\nkernel = np.ones((3,3), np.uint8)\nerode = cv2.erode(blurred, kernel, iterations = 3)\nplt.imshow(erode)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c12ae30d2df7105c33a84c2dd1221bc15d9e53cc"},"cell_type":"markdown","source":"Canny for edge detection"},{"metadata":{"trusted":true,"_uuid":"91d7eb8db26ce11027b607dd8802a65b2e0a816f"},"cell_type":"code","source":"#cannyedge \ndef canny_edge_detector(input_img, threshold1, threshold2, draw=True, save=True):\n    canny_img = cv2.cvtColor(np.copy(input_img), cv2.COLOR_BGR2GRAY)\n    edges = cv2.Canny(canny_img, threshold1, threshold2)\n    return edges","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"c199188800edc202e1fe3ce7d1fb871678f16fca"},"cell_type":"code","source":"#try adding Eroding before edge detection(increase black lines)\ncanny_edges = canny_edge_detector(input_img=erode, threshold1=100, threshold2=150) \nplt.imshow(canny_edges)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"468e9089923b97b522b6654832952cbfe0be1f7b"},"cell_type":"markdown","source":"dilation: A kernel(a matrix of odd size(3,5,7)) is convolved with the image  \nA pixel element in the original image is ‘1’ if atleast one pixel under the kernel is ‘1’.  \nIt increases the white region in the image or size of foreground object increases  "},{"metadata":{"trusted":true,"_uuid":"0f405e1732a105baceed86d26dbecc74447bbd8c"},"cell_type":"code","source":"#close the small line gaps using dilation\nkernel = np.ones((5,5), np.uint8)\ndilation_canny = cv2.dilate(canny_edges, kernel, iterations = 3)\ncanny_blurred = cv2.GaussianBlur(dilation_canny, (3,3), 0) # Remove noise\nplt.imshow(canny_blurred)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"18c5d00241c9ec592d62fae9dd63d68220cebd73"},"cell_type":"markdown","source":"## step 2: get whale contour"},{"metadata":{"trusted":true,"_uuid":"c26829ed78ca249dfa80c43d7148b92264372c39"},"cell_type":"code","source":"from skimage import measure\nfrom shapely.geometry import Polygon,Point\nmin_contour_size = canny_blurred.size * 5 / 100\nprint(\"min size:\"+str(min_contour_size))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"60c445373a0acb4753ff22eeb2e5fbf3118054a1"},"cell_type":"markdown","source":"contour detection:  \nFind iso-valued contours in a 2D array for a given level value.  \nUses the “marching squares” method to compute a the iso-valued contours of the input 2D array for a particular level value. Array values are linearly interpolated to provide better precision for the output contours."},{"metadata":{"trusted":true,"_uuid":"61752b39b1b5c7b6ab96956d002b15fa27209fc7"},"cell_type":"code","source":"#box=(x0,y0,x1,t1)\ndef calc_box_size(box):\n    box_width=box[2]-box[0]\n    box_hight=box[3]-box[1]\n    box_area=box_width*box_hight\n    return box_area\n\ndef bounding_rectangle(polygon):\n  x0=min(polygon[:, 1])\n  y0=min(polygon[:, 0])\n  x1=max(polygon[:, 1])\n  y1=max(polygon[:, 0])\n  return x0,y0,x1,y1\n\ndef find_max_contour(image):\n  contours = measure.find_contours(image.copy(), 0.8)\n  max_area=0\n  max_x=0\n  max_y=0\n  min_x=image.shape[0]\n  min_y=image.shape[1]\n  #get def_box\n  for n, contour in enumerate(contours):\n    contour[:, 1], contour[:, 0]\n    max_c_x=max(contour[:, 1])\n    max_c_y=max(contour[:, 0])\n    min_c_x=min(contour[:, 1])\n    min_c_y=min(contour[:, 0])\n    if max_c_x>max_x:\n      max_x=max_c_x\n    if max_c_y>max_y:\n      max_y=max_c_y\n    if min_c_x<min_x:\n      min_x=min_c_x\n    if min_c_y<min_y:\n      min_y=min_c_y\n    \n  def_box=(min_x,min_y,max_x,max_y)\n  max_contour=None\n  for n, contour in enumerate(contours):\n    if contour.shape[0]<3: continue\n    box=bounding_rectangle(contour)    \n    box_size=calc_box_size(box)\n\n    if max_contour is None:\n      max_contour=contour\n      max_area=box_size\n    if box_size>max_area:\n      max_contour=contour\n      max_area=box_size\n  return max_contour,max_area,def_box","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"57e4ef48e90c2c0dbc36e5e68f9c0114bfa72b49"},"cell_type":"markdown","source":"get contour with longiest contour line"},{"metadata":{"trusted":true,"_uuid":"dc50bdc719f52d83bff545e2f8366a539c0cc604"},"cell_type":"code","source":"contour,area,def_box=find_max_contour(canny_blurred) \nplt.imshow(img)\nplt.plot(contour[:, 1], contour[:, 0], linewidth=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"997607253d7ab4af89aedd291ee091b90247173a"},"cell_type":"markdown","source":"## *step 3: get bounding box*"},{"metadata":{"trusted":true,"_uuid":"950f43419e5e0ac8146a986607533dff27d75653","scrolled":false},"cell_type":"code","source":"import matplotlib.patches as patches\nbox=bounding_rectangle(contour)\nplt.imshow(img)\nplt.plot(contour[:, 1], contour[:, 0], linewidth=1)\n# Get the current reference\nax = plt.gca()\n# Create a Rectangle patch\nrect = patches.Rectangle((box[0],box[1]),box[2]-box[0],box[3]-box[1],linewidth=1,edgecolor='r',facecolor='none')\n# Add the patch to the Axes\nax.add_patch(rect)\ndef_rect = patches.Rectangle((def_box[0],def_box[1]),def_box[2]-def_box[0],def_box[3]-def_box[1],linewidth=1,edgecolor='g',facecolor='none')\n# Add the patch to the Axes\nax.add_patch(def_rect)\ndef_box","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f40958aba7009329f8b281d310b390f059c93bfe"},"cell_type":"markdown","source":"## step 4: validate bounding box"},{"metadata":{"trusted":true,"_uuid":"9300c4882873da9748a57ead8a1e4d0e185c5ca9"},"cell_type":"code","source":"def get_box_center(box):\n    #box polygon\n    x0=box[0]\n    y0=box[1]\n    x1=box[2]\n    y1=box[3]\n    x2=x1\n    y2=y0\n    x3=x0\n    y3=y1\n    in_box=[[x0,y0],[x1,y1],[x2,y2],[x3,y3]]\n    polygon_box = Polygon(in_box)\n    box_centr=polygon_box.centroid.coords\n    return box_centr\n\ndef get_serrounding_box_for_p(point,img_width,img_high,margin=0.2):\n    x0=point[0]-margin*img_width\n    y0=point[1]-margin*img_high\n    x1=point[0]+margin*img_width\n    y1=point[1]+margin*img_high\n    return (x0,y0,x1,y1)\n\n    \ndef validate_bb(image, box):\n    if box is None:\n        return False\n    #check min size\n    box_area=calc_box_size(box)\n    min_contour_size = image.size * 5 / 100\n    if box_area<min_contour_size:\n        return False\n    \n    #box polygon\n    box_centr=get_box_center(box)[0]\n    \n    #default polygon\n    img_centr=get_box_center((0,0,image.shape[1],image.shape[0]))[0]\n    srr_box=get_serrounding_box_for_p(img_centr,image.shape[1],image.shape[0],margin=0.2)\n    \n    #check box centered\n    if  box_centr[0]>srr_box[0] and box_centr[0]< srr_box[2] and box_centr[1]>srr_box[1] and box_centr[1]<srr_box[3]:\n        return True\n    \n    return False\n\nprint(validate_bb(img,box))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a89d8869f6ab6b062cedadae5432215f44ed6932"},"cell_type":"code","source":"#get BB coordinates\ndef get_whale_bb(image_path):\n    img=cv2.imread(image_path)\n    blurred = cv2.GaussianBlur(img, (7,7), 0) # Remove noise\n    kernel = np.ones((3,3), np.uint8) \n    erode = cv2.erode(blurred, kernel, iterations = 3)\n    \n    ##find edges\n    canny_edges = canny_edge_detector(input_img=erode, threshold1=100, threshold2=150)   \n    kernel = np.ones((5,5), np.uint8)\n    dilation_canny = cv2.dilate(canny_edges, kernel, iterations = 3)#close the small line gaps using dilation\n    canny_blurred = cv2.GaussianBlur(dilation_canny, (3,3), 0) # Remove noise\n    \n    ##find contour\n    contour,area,def_box=find_max_contour(canny_blurred)\n    \n    ##find bb\n    box=None\n    if contour is not None:\n        box=bounding_rectangle(contour)\n        #check that box is not none, more than min size, with centroid in the center of image\n        valid=validate_bb(img, box)\n        if valid:\n            return box\n    \n    valid=validate_bb(img, def_box)\n    if valid:\n        return def_box\n    return None","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3973ad5559870165e3cfea038efa449844ceaaa5"},"cell_type":"markdown","source":"## step 5: output bb for all test and train set to csv"},{"metadata":{"trusted":true,"_uuid":"24d1b959976c9ae08fb3f9e4bde172d0df466fd6"},"cell_type":"code","source":"bb_train = pd.DataFrame(columns=['image','x0','y0','x1','y1'])\nfor i in range(0,25):\n    img_path=train_paths[i]\n    bb=get_whale_bb(img_path)\n    if bb is None:\n        continue\n    tmpdf=pd.DataFrame([[img_path,bb[0],bb[1],bb[2],bb[3]]],columns=['image','x0','y0','x1','y1'])\n    bb_train=bb_train.append(tmpdf)\n\n#look at examples\nn=len(bb_train)\nimgs_df=bb_train[:n].reset_index()\nper_row=5\nrows=n//per_row\ncols      = min(per_row, n)\nfig, axes = plt.subplots(rows,cols, figsize=(24//per_row*cols,24//per_row*rows))\nfor ax in axes.flatten(): \n    ax.axis('off')\nfor i,ax in enumerate(axes.flatten()): \n#     print (i)\n    image_path=imgs_df.loc[i,'image']\n    x0=float(imgs_df.loc[i,'x0'])\n    y0=float(imgs_df.loc[i,'y0'])\n    x1=float(imgs_df.loc[i,'x1'])\n    y1=float(imgs_df.loc[i,'y1'])\n    ax.imshow(cv2.imread(image_path))\n    \n    rect = patches.Rectangle((x0,y0),x1-x0,y1-y0,linewidth=1,edgecolor='r',facecolor='none')\n    ax.add_patch(rect) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"29b35662e3ef910e005db3d0c829d98f0090da0f"},"cell_type":"code","source":"#train bb \nprint(\"total train images:\"+str(len(train_paths)))\nbb_train = pd.DataFrame(columns=['image','x0','y0','x1','y1'])\nfor i in range(len(train_paths)):\n    if i%1000==0:\n        print(i)\n    img_path=train_paths[i]\n    bb=get_whale_bb(img_path)\n    if bb is None:\n        continue\n    tmpbb=pd.DataFrame([[img_path,bb[0],bb[1],bb[2],bb[3]]],columns=['Image','x0','y0','x1','y1'])\n    bb_train=bb_train.append(tmpbb)\n\nprint(\"total croped train images:\"+str(len(bb_train)))\nbb_train.to_csv('boxs_train.csv', header=True, index=False)\nprint(\"finished!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"781bd38097ef2a06541e14b2a89b73c4fe193f32"},"cell_type":"code","source":"#test bb \nprint(\"total test images:\"+str(len(train_paths)))\nbb_test = pd.DataFrame(columns=['image','x0','y0','x1','y1'])\nfor i in range(len(test_paths)):\n    if i%1000==0:\n        print(i)\n    img_path=test_paths[i]\n    bb=get_whale_bb(img_path)\n    if bb is None:\n        continue\n    tmpbb=pd.DataFrame([[img_path,bb[0],bb[1],bb[2],bb[3]]],columns=['Image','x0','y0','x1','y1'])\n    bb_test=bb_test.append(tmpbb)\n\nprint(\"total croped test images:\"+str(len(bb_test)))\nbb_test.to_csv('boxs_test.csv', header=True, index=False)\nprint(\"finished!\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"288f99bce6cdbed84328774dd21622ae858dab46"},"cell_type":"markdown","source":""}],"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}