{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"https://www.kaggle.com/code/victorlouisdg/plant-pathology-opencv-background-removal","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport cv2\nimport os\nimport random\nfrom tqdm import tqdm\ntqdm.pandas()\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.axes_grid1 import ImageGrid","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-13T04:32:24.716966Z","iopub.execute_input":"2023-05-13T04:32:24.717704Z","iopub.status.idle":"2023-05-13T04:32:24.726089Z","shell.execute_reply.started":"2023-05-13T04:32:24.717609Z","shell.execute_reply":"2023-05-13T04:32:24.724676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"paths=[]\nt=0\nfor dirname, _, filenames in os.walk('/kaggle/input/happy-whale-and-dolphin/train_images'):\n    if t<30:\n        for filename in filenames:\n            paths+=[(os.path.join(dirname, filename))]\n            t+=1","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:24.728431Z","iopub.execute_input":"2023-05-13T04:32:24.728835Z","iopub.status.idle":"2023-05-13T04:32:37.429146Z","shell.execute_reply.started":"2023-05-13T04:32:24.728782Z","shell.execute_reply":"2023-05-13T04:32:37.427431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_image(path):\n    image = cv2.imread(path)\n    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\ntrain_images = pd.Series(random.sample(paths,3)).progress_apply(load_image)","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2023-05-13T04:32:37.432290Z","iopub.execute_input":"2023-05-13T04:32:37.432723Z","iopub.status.idle":"2023-05-13T04:32:38.094825Z","shell.execute_reply.started":"2023-05-13T04:32:37.432666Z","shell.execute_reply":"2023-05-13T04:32:38.092434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This function is used to initialize the mask used for the GrabCut algorithm. The GrabCut algorithm is a type of graph cut algorithm used for image segmentation, which uses pre-specified masks to determine background/foreground regions and then segments the image based on the results.\n\nThe function arguments are h and w integer values representing the height and width of the mask. The function creates a mask of the specified size, based on h and w, and divides the area inside the mask into background and foreground. ","metadata":{}},{"cell_type":"code","source":"def init_grabcut_mask(h, w):\n    mask = np.ones((h, w), np.uint8) * cv2.GC_PR_BGD\n    mask[h//4:3*h//4, w//4:3*w//4] = cv2.GC_PR_FGD\n    mask[2*h//5:3*h//5, 2*w//5:3*w//5] = cv2.GC_FGD\n    return mask\n\nplt.imshow(init_grabcut_mask(3*136, 3*205))","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:38.097366Z","iopub.execute_input":"2023-05-13T04:32:38.097804Z","iopub.status.idle":"2023-05-13T04:32:38.431019Z","shell.execute_reply.started":"2023-05-13T04:32:38.097737Z","shell.execute_reply":"2023-05-13T04:32:38.428992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This function is used to draw contour lines and bounding boxes on the image using the mask generated by the GrabCut algorithm. The GrabCut algorithm separates the background and foreground regions and generates an output mask with corresponding mask values for each. Use this mask to detect the contour lines of the image and draw the bounding box.\n\nThe arguments of the function are the image to draw and the mask generated by the GrabCut algorithm.","metadata":{}},{"cell_type":"code","source":"def add_contours(image, mask):\n    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n    \n    if len(contours) != 0:\n        cv2.drawContours(image, contours, -1, (255, 0, 0), 3)\n        c = max(contours, key = cv2.contourArea)\n        x,y,w,h = cv2.boundingRect(c)\n        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0) ,2)\n    ","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:38.434244Z","iopub.execute_input":"2023-05-13T04:32:38.435207Z","iopub.status.idle":"2023-05-13T04:32:38.453333Z","shell.execute_reply.started":"2023-05-13T04:32:38.434934Z","shell.execute_reply":"2023-05-13T04:32:38.451491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This code defines a function remove_background that takes an input image and returns the same image with the background removed. ","metadata":{}},{"cell_type":"markdown","source":"### cv2.grabCut\nThe GrabCut algorithm is used for image segmentation, which involves dividing an image into multiple regions or objects based on their characteristics, such as color, texture, or intensity.","metadata":{}},{"cell_type":"markdown","source":"### cv2.GC_INIT_WITH_MASK\ncv2.GC_INIT_WITH_MASK is a flag that can be passed as a parameter to the cv2.grabCut function in OpenCV. This flag indicates that the GrabCut algorithm should be initialized with an initial mask provided by the user, rather than automatically computing an initial mask","metadata":{}},{"cell_type":"markdown","source":"### cv2.bitwise_and\ncv2.bitwise_and is a function in the OpenCV library that performs a bitwise AND operation between two images or between an image and a scalar value. It takes two input images, src1 and src2, and produces an output image, dst, that is the same size and type as the input images.","metadata":{}},{"cell_type":"code","source":"#init_grabcut_mask\n#cv2.grabCut\n#cv2.GC_INIT_WITH_MASK\n#cv2.bitwise_and\n#add_contours\n\ndef remove_background(image):\n    h, w = image.shape[:2]\n    mask = init_grabcut_mask(h, w)\n    bgm = np.zeros((1, 65), np.float64)\n    fgm = np.zeros((1, 65), np.float64)\n    cv2.grabCut(image, mask, None, bgm, fgm, 1, cv2.GC_INIT_WITH_MASK)\n    mask_binary = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')\n    result = cv2.bitwise_and(image, image, mask = mask_binary)\n    add_contours(result, mask_binary) # optional, adds visualizations\n    return result\n\n","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:38.456179Z","iopub.execute_input":"2023-05-13T04:32:38.457315Z","iopub.status.idle":"2023-05-13T04:32:38.472834Z","shell.execute_reply.started":"2023-05-13T04:32:38.457224Z","shell.execute_reply":"2023-05-13T04:32:38.471725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ImageGrid\nImageGrid is a class in the matplotlib library that is used to create a grid of images. It can be used to display a collection of images in a grid layout, where each image is displayed in its own cell of the grid.","metadata":{}},{"cell_type":"code","source":"%%time\n\nrows, cols = (len(train_images), 2)\naxes_pad = 0.2\nfig_h = 4.0 * rows + axes_pad * (rows-1) \nfig_w = 4.0 * cols + axes_pad * (cols-1) \nfig = plt.figure(figsize=(fig_w, fig_h))\ngrid = ImageGrid(fig, 111, nrows_ncols=(rows, cols), axes_pad=0.2)   \n        \nfor i, ax in enumerate(grid):\n    im = cv2.resize(train_images.iloc[i // 2], (3*205, 3*136))\n    if i % 2 == 1:\n        im = remove_background(im)\n    ax.imshow(im)    ","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:38.474486Z","iopub.execute_input":"2023-05-13T04:32:38.474892Z","iopub.status.idle":"2023-05-13T04:32:57.411144Z","shell.execute_reply.started":"2023-05-13T04:32:38.474833Z","shell.execute_reply":"2023-05-13T04:32:57.409620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"for comparison<br/>\nhttps://www.kaggle.com/code/stpeteishii/whale-tail-manual-background-removal","metadata":{}},{"cell_type":"code","source":"\nfor img in train_images:\n    img=cv2.resize(img, dsize=(3*205, 3*136))\n    #img=cv2.resize(img, dsize=None, fx=0.1, fy=0.1)\n    H=img.shape[0]\n    W=img.shape[1]\n    Ps=[[0,0],[10,0],[0,10], \n        [H-1,0],[H-11,0],[H-1,10], \n        [0,W-1],[10,W-1],[0,W-11], \n        [H-1,W-1],[H-11,W-1],[H-1,W-11]]\n    \n    for P in Ps:\n        p0=P[0]\n        p1=P[1]\n        a0=img[p0,p1,0]*0.7\n        a1=img[p0,p1,0]*1.3\n        b0=img[p0,p1,1]*0.7\n        b1=img[p0,p1,1]*1.3\n        c0=img[p0,p1,2]*0.7\n        c1=img[p0,p1,2]*1.3\n\n        for h in range(H):\n            for w in range(W):\n                if a0<img[h,w,0]<a1 and b0<img[h,w,1]<b1 and c0<img[h,w,2]<c1:\n                    img[h,w,:]=np.array([255,255,255])\n\n    plt.imshow(img)\n    for yx in Ps:\n        y=yx[0]\n        x=yx[1]\n        plt.plot(x,y,'ro',markersize=1)\n    plt.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-13T04:32:57.413183Z","iopub.execute_input":"2023-05-13T04:32:57.413817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}