Image processing does not always provide beautiful images. Images are often noisy. If there is noise, it may be removed using a technique called "smoothing" or "morphology conversion".
This time, we will use Python to perform morphological conversion of images using OpenCV.
** Morphology conversion ** is mainly to perform "** contraction " and " expansion **" processing on binary images. Morphology is the process of "morphology," or shape.
A "binary image" is a binarized image. Binarization is the process of converting an image into two gradations, white and black.
The environment uses Google Colaboratory. The Python version is below.
import platform
print("python " + platform.python_version())
# python 3.6.9
Now let's write the code. First, import OpenCV.
import cv2
In addition, import the following to display the image in Colaboratory.
from google.colab.patches import cv2_imshow
Prepare a sample image as well.
Now, let's display the prepared sample image.
img = cv2.imread(path) #path specifies where the image is placed
cv2_imshow(img)
The grayscaled image is below.
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2_imshow(img_gray)
The binarized image of the grayscale image is as follows. This time, I set the threshold to 180.
threshold = 180
_, img_th = cv2.threshold(img_gray, threshold, 255, cv2.THRESH_BINARY)
cv2_imshow(img_th)
Furthermore, let's display a black-and-white inverted image of the binarized image. I will perform morphology conversion on this image.
img_bw = cv2.bitwise_not(img_th)
cv2_imshow(img_bw)
In addition, prepare an image with noise as an image to be used later. This time, I prepared two types of noise-containing images using Salt-and-pepper noise.
import numpy as np
row, col, ch = img.shape
img_s = img.copy()
img_p = img.copy()
pts_x = np.random.randint(0, col-1 , 1000)
pts_y = np.random.randint(0, row-1 , 1000)
img_s[(pts_y,pts_x)] = (255, 255, 255)
img_p[(pts_y,pts_x)] = (0, 0, 0)
imgs = cv2.hconcat([img_s, img_p])
cv2_imshow(imgs)
These images are also grayscale, binarized, and black and white inverted.
#grayscale
img_s = cv2.cvtColor(img_s, cv2.COLOR_BGR2GRAY)
img_p = cv2.cvtColor(img_p, cv2.COLOR_BGR2GRAY)
#Binarization
threshold = 180
_, img_s = cv2.threshold(img_s, threshold, 255, cv2.THRESH_BINARY)
_, img_p = cv2.threshold(img_p, threshold, 255, cv2.THRESH_BINARY)
#Black and white inversion
img_s = cv2.bitwise_not(img_s)
img_p = cv2.bitwise_not(img_p)
imgs = cv2.hconcat([img_s, img_p])
cv2_imshow(imgs)
Now, let's introduce how to perform morphological conversion on an image.
Import numpy in advance for use in the following.
import numpy as np
With erosion, ** shrink the white areas **. As a result, the white areas become smaller and thinner, and the black areas increase. This is an effective process for removing white noise in an image or separating multiple connected objects.
Now, let's display the shrunk image side by side with the original image.
kernel = np.ones((3, 3), np.uint8)
img_ero = cv2.erode(img_bw, kernel, iterations=1)
imgs = cv2.hconcat([img_bw, img_ero])
cv2_imshow(imgs)
You can see that the white part is smaller and thinner than the original image.
cv2.erode has three arguments. The first argument is the target image. The second argument is what is called the kernel size. When one point of the image is decided, it shows how much area around it is included. Think of it as the size of a box. The third argument is what is called an iteration. Iteration means "iteration" and here specifies how many times the process should be performed. In the above, the contraction process is performed only once.
Now, let's display the shrink-processed image by changing the kernel size value in various ways.
kernel_1 = np.ones((1, 1), np.uint8)
kernel_2 = np.ones((3, 3), np.uint8)
kernel_3 = np.ones((5, 5), np.uint8)
img_1 = cv2.erode(img_bw, kernel_1, iterations=1)
img_2 = cv2.erode(img_bw, kernel_2, iterations=1)
img_3 = cv2.erode(img_bw, kernel_3, iterations=1)
imgs = cv2.hconcat([img_1, img_2, img_3])
cv2_imshow(imgs)
You can see that the larger the kernel size, the more it shrinks, and the white areas become smaller and thinner.
Next, let's display the image that has been shrunk by changing the iteration value.
kernel = np.ones((3, 3), np.uint8)
img_1 = cv2.erode(img_bw, kernel, iterations=1)
img_2 = cv2.erode(img_bw, kernel, iterations=3)
img_3 = cv2.erode(img_bw, kernel, iterations=5)
imgs = cv2.hconcat([img_1, img_2, img_3])
cv2_imshow(imgs)
Again, the shrinking process is repeated for the number of iterations, so the larger the value, the more shrinking.
Dilation ** dilates the white areas **. This is the reverse of contraction. In other words, as a result, the black areas become smaller and thinner, and the white areas increase.
Now, let's display the expanded image side by side with the original image.
img_dil = cv2.dilate(img_bw, kernel, iterations = 1)
imgs = cv2.hconcat([img_bw, img_dil])
cv2_imshow(imgs)
You can see that the white part is thicker and larger than the original image.
The arguments for cv2.dilate are similar to the arguments for contraction cv2.erode.
The opening process is the process of expanding after contracting. The white part can be made smaller by shrinking, and the size can be restored by expanding. Therefore, it is an effective process for removing ** white noise **.
Let's display the image with noise and the image with the opening process side by side.
img_opening = cv2.morphologyEx(img_p, cv2.MORPH_OPEN, kernel)
imgs = cv2.hconcat([img_p, img_opening])
cv2_imshow(imgs)
As a result of the opening process, you can see that the white noise has been removed.
The closing process is the reverse of the opening process. The black part can be made smaller by expansion, and the size can be restored by contraction. Therefore, it is an effective process for removing ** black noise **.
Let's display the image with noise and the image with closing processing side by side.
img_closing = cv2.morphologyEx(img_s, cv2.MORPH_CLOSE, kernel)
imgs = cv2.hconcat([img_s, img_closing])
cv2_imshow(imgs)
As a result of the closing process, you can see that the black noise has been removed.
Morphology gradient is the process of taking the difference between an expanded image and a contracted image. This will result in the contouring of the object.
Let's display an image with a morphology gradient.
img_gradient = cv2.morphologyEx(img_bw, cv2.MORPH_GRADIENT, kernel)
cv2_imshow(img_gradient)
You can see that the outline of the object is taken.
This time, I used Python to perform morphological conversion of the image by OpenCV.
We introduced "contraction", "expansion", "opening process", "closing process", and "morphology gradient" as morphology conversions. In particular, opening processing and closing processing are effective methods for removing fine noise. Consider opening treatment for white noise and closing treatment for black noise.
There is also a method called "smoothing" as a noise removal method, so I think you should try this as well.
See below for more information on morphology transformations and smoothing.
-Morphological conversion -I tried "smoothing" the image with Python + OpenCV
Recommended Posts