pythonopencvdilation

Dilate in only one direction


I have an issue using erode and dilate, I'm not sure I understand how to properly use the parameters.

I have this picture:

enter image description here

Using this piece of code:

def dilate_and_erode(self):

        img = self.img

        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        _, thresh = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        
        
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
        res = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
        
        dilated = cv2.dilate(res, kernel)
        
        eroded=cv2.erode(dilated,kernel)

        img_contours = cv2.findContours(eroded, cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_SIMPLE)[-2]
        img_contours = sorted(img_contours, key=cv2.contourArea)

        ctr = []
        for i in img_contours:
            if cv2.contourArea(i) > 100:
                ctr.append(i)

        mask = np.zeros(img.shape[:2], np.uint8)
        cv2.drawContours(mask, ctr,-1, 255, -1)
        new_img = cv2.bitwise_and(img, img, mask=mask)

        cv2.imshow("Original Image", img)
        cv2.imshow("New image", new_img)
        cv2.imshow("Mask", mask)
        cv2.waitKey(0)

I get this :

enter image description here

Which is not exactly what I want, I'd like to remove the black noise in the top of the picture

enter image description here

Any advices would be greatly appreciated !


Solution

  • It's not difficult to implement dilation in one direction using for loops, but it's a bit boring...

    Suggested solution:
    Move the image up by one pixel, take the maximum of image and "moved image"; repeat the process few times.

    The suggested solution is inefficient in terms of complexity, but since loops in Python are so slow, its going to be faster than using nested for loops.

    Here is a code sample:

    import cv2
    import numpy as np
    
    new_img = cv2.imread('new_image.png')
    
    for i in range(15):
        new_img[0:-1, :, :] = np.maximum(new_img[0:-1, :, :], new_img[1:, :, :])
    

    Result (new_img):
    enter image description here