“This is the 12th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Brief introduction to morphological transformation

Transformations are usually performed on binary images based on the shape of the image. The specific operation is determined by the nuclear structure element, which determines the nature of the operation. Expansion and corrosion are two basic operators in the field of morphological transformation. In addition, the open and closed operations are two important operations, which can be obtained by the above two operations (expansion and corrosion). Finally, there are three other commonly used transformation operations that are based on variations or combinations of previous operations.

Expansion operation and corrosion operation

The main function of binary image expansion operation is to enlarge the boundary area of foreground object gradually. This means that the area of the foreground object will become larger, and the holes within these areas will shrink:

dilation = cv2.dilate(image, kernel, iterations=1)
Copy the code

The main effect of corrosion operation on binary image is to gradually erode away the boundary area of foreground object. This means that the foreground object’s region becomes smaller, and the voids within those regions become larger:

erosion = cv2.erode(image, kernel, iterations=1)
Copy the code

Next, the expansion operation and corrosion operation are used:

image_names = ['test1.png'.'test2.png'.'test3.png']
path = 'morpho_test_imgs'

kernel_size_3_3 = (3.3)
kernel_size_5_5 = (5.5)

def load_all_test_images() :
    test_morph_images = []
    for index_image, name_image in enumerate(image_names):
        image_path = os.path.join(path, name_image)
        test_morph_images.append(cv2.imread(image_path))
    return test_morph_images

def show_with_matplotlib(color_img, title, pos) :
    img_RGB = color_img[:, :, ::-1]
    ax = plt.subplot(3.3, pos)
    plt.imshow(img_RGB)
    plt.title(title, fontsize=8)
    plt.axis('off')

def erode(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    erosion = cv2.erode(image, kernel, iterations=1)
    return erosion

def dilate(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    dilation = cv2.dilate(image, kernel, iterations=1)
    return dilation

test_images = load_all_test_images()

for index_image,image in enumerate(test_images):
    show_with_matplotlib(image, 'test img_{}'.format(index_image + 1), index_image * 3 + 1)
    img_1 = erode(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_1, 'erode_{}'.format(index_image + 1), index_image * 3 + 2)
    img_2 = dilate(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_2, 'dilate_{}'.format(index_image + 1), index_image * 3 + 3)
Copy the code

Open and closed operations

The open operation performs corrosion and then expands using the same structural elements (or cores). In this way, corrosion can be applied to eliminate a small number of unwanted pixels (for example, salt-and-pepper noise). Corrosion indiscriminately affects all areas of the image. By performing expansion operations after corrosion, some of the effects of excessive corrosion can be reduced:

opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
Copy the code

Closed budgets can also be derived from corrosion and expansion operations, which perform expansion first and then corrosion. The expansion operation is usually used to fill holes in the image. However, swelling also makes a small group of noisy pixels larger. This effect of inflation will be reduced by applying corrosion to the image after inflation:

closing = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
Copy the code

Next, we actually use the open and closed operations:

The # build_kernel() and show_with_matplotlib() functions are the same as in 4.1
def closing(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    clos = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
    return clos

def opening(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    ope = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
    return ope

for index_image,image in enumerate(test_images):
    show_with_matplotlib(image, 'test img_{}'.format(index_image + 1), index_image * 3 + 1)
    img_1 = closing(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_1, 'closing_{}'.format(index_image + 1), index_image * 3 + 2)
    img_2 = opening(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_2, 'opening_{}'.format(index_image + 1), index_image * 3 + 3)

plt.show()
Copy the code

Morphological gradient operation

The morphological gradient operation is defined as the difference between the expansion and corrosion of the input image:

morph_gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)
Copy the code

Usage of morphological gradient operation:

The # build_kernel() function is the same as in 4.1
def show_with_matplotlib(color_img, title, pos) :
    img_RGB = color_img[:, :, ::-1]
    ax = plt.subplot(2.3, pos)
    plt.imshow(img_RGB)
    plt.title(title, fontsize=8)
    plt.axis('off')

def morphological_gradient(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    morph_gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)
    return morph_gradient
    
for index_image,image in enumerate(test_images):
    print(index_image)
    show_with_matplotlib(image, 'test img_{}'.format(index_image + 1), index_image + 1)
    img = morphological_gradient(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img, 'gradient_{}'.format(index_image + 1), index_image + 4)
Copy the code

Top hat operation and low hat (black hat) operation

The top hat operation is defined as the difference between the input image and the image open operation:

top_hat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, kernel)
Copy the code

The black hat operation is defined as the difference between the input image and the closed operation of the input image:

black_hat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, kernel)
Copy the code

Top hat operation and low hat operation usage:

The # build_kernel() and show_with_matplotlib() functions are the same as in 4.1
def black_hat(image, kernel_type, kernel_size) :
    kernel = build_kernel(kernel_type, kernel_size)
    black = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, kernel)
    return black

def opening_and_closing(image, kernel_type, kernel_size) :
    opening_img = opening(image, kernel_type, kernel_size)
    closing_img = closing(opening_img, kernel_type, kernel_size)
    return closing_img

for index_image,image in enumerate(test_images):
    show_with_matplotlib(image, 'test img_{}'.format(index_image + 1), index_image * 3 + 1)
    img_1 = top_hat(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_1, 'top_hat_{}'.format(index_image + 1), index_image * 3 + 2)
    img_2 = black_hat(image, cv2.MORPH_RECT, (3.3))
    show_with_matplotlib(img_2, 'black_hat_{}'.format(index_image + 1), index_image * 3 + 3)

plt.show()
Copy the code

Structural elements

OpenCV provides cv2. GetStructuringElement () function is used to construct the structure elements. This function outputs the desired core (NumPy array of type Uint8), which takes two arguments — the shape and size of the core. Three core shapes are available in OpenCV:

Nuclear shape instructions
cv2.MORPH_RECT Rectangular nuclear
cv2.MORPH_ELLIPSE Oval nucleus
cv2.MORPH_CROSS Cross the nuclear

Applied morphologic transformation

You can use different core sizes and shapes, morphologies and images. Test for different nuclear shapes and sizes. For example, here is the output using a rectangular core (cv2.morph_rect) with a core size (3, 3) :

Output when using a rectangular core (cv2.morph_rect) with a core size (5, 5) :

Output from cross (cv2.morph_cross) with core size (3, 3) :

Output from cross (cv2.morph_cross) with core size (5, 5) :

Morphological operation is a very useful technique in image preprocessing, which can eliminate some noise that interferes with the correct image processing or deal with defects in image structure.

A link to the

OpenCV basic image operations