1

I am very new to image processing in Python and need your guidance.

I want to mask my stacked images (sample of notch rock) based on edge detection. I am trying to use cv2.Canny edge detection, cv2.findContours, cv2.drawContours, cv2.threshold, and cv2.floodFill to do this. I then applied it to my image slices. However, when I check the results, some of the slices are not properly masked. I am not sure in which part should I improve my code.

I uploaded my image slices in here: Image slices

And I use this code to do the masking:

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import glob
import os
from tqdm import tqdm
import cv2


# =============================================================================
# Working directory
# =============================================================================
workdir = r'filepath to image slices'

# =============================================================================
# List files 
# =============================================================================
lsfiles = sorted(glob.glob(workdir+'/*.tif*'))

# =============================================================================
# Function
# =============================================================================
def gauss_canny_mask(img_fname, savfolder):
    image3 = cv2.imread(img_fname,0)
    blurred_image = cv2.GaussianBlur(image3.copy(),(5,5),0)
    def auto_canny(image, sigma=0.33):
        # compute the median of the single channel pixel intensities
        v = np.median(image)
        # apply automatic Canny edge detection using the computed median
        lower = int(max(0, (1.0 - sigma) * v))
        upper = int(min(255, (1.0 + sigma) * v))
        edged = cv2.Canny(image, lower, upper)
        # return the edged image
        return edged
    edges3 = auto_canny(blurred_image)
    
    contours, hierarchy = cv2.findContours(edges3, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    image_copy = image3.copy()
    cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
    th, im_th = cv2.threshold(image_copy, 1, 30, cv2.THRESH_BINARY_INV);
 
    # Copy the thresholded image.
    im_floodfill = im_th.copy()
 
    # Mask used to flood filling.
    # Notice the size needs to be 2 pixels than the image.
    h, w = image_copy.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)
 
    # Floodfill from point (0, 0)
    cv2.floodFill(im_floodfill, mask, (0,0), 255);
 
    # Invert floodfilled image
    im_floodfill_inv = cv2.bitwise_not(im_floodfill)
 
    # Combine the two images to get the foreground.
    im_out = im_th | im_floodfill_inv
    
    masked_img = image3.copy()
    img_out = np.array(im_out !=0, dtype=bool)
    masked_img[~img_out] = 0

    masked_img = Image.fromarray(masked_img)
    masked_img.save(savfolder)

# =============================================================================
# Test function
# =============================================================================
for img_file_name in lsfiles:
    savfolder = '\\'.join(workdir.split('\\')[:-1])+'\\'+'Mask'+'\\'+'Mask_'+img_file_name.split('\\')[-1]
    gauss_canny_mask(img_file_name, savfolder)

Any guidance and help would be very much appreciated!

Thanks so much!

EDIT: This is example of expected masked image that I want to have Masked image

But, some of them are not masked well enough: Fail Fail2

Nana
  • 11
  • 2
  • you have to post the stack trace, and also attach the images within the question and not as hyper links – Kulasangar Feb 01 '23 at 09:05
  • Hi I am not sure how to attach images within the question, I thought I did that but it appeared to give me the link. This is my first time posting questions in here. – Nana Feb 01 '23 at 14:47

0 Answers0