OpenCV 09 (morphology)

1. Morphology

Morphology refers to a series of image processing techniques that deal with the shape characteristics of images.

  • The basic idea of ​​morphology is to use a special structural element (essentially a convolution kernel) to measure or extract the corresponding shape or feature in the input image for further image analysis and target recognition.
  • These processing methods basically process binary images , that is, black and white images
  • The convolution kernel determines the effect of image processing


Commonly used basic operations in morphology are:

    - Expansion and corrosion
    - Opening operations
    - Closing operations
    - Top hat
    - Black hat

1.1 Global binarization of images 

Binarization: Turn each pixel of the image into two values, such as 0, 255

0 and 255: 0 is black and 255 is white

01: 0 is black, 1 is white

- threshold(src, thresh, maxval, type[, dst])

  - src is preferably a grayscale image

  - thresh: threshold

  - maxval: maximum value, the maximum value is not necessarily 255

  - type: operation type. Common operation types are as follows:

 import cv2
  import numpy as np
  
  img = cv2.imread('./dog.jpeg')
  
  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  
  # 返回两个结果, 一个是阈值, 另一个是处理后的图片
  ret, dst = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY)
  
  cv2.imshow('dog', np.hstack((gray, dst)))
  
  cv2.waitKey(0)
  cv2.destroyAllWindows()

1.2 Adaptive threshold binarization

In the previous part we used a global threshold, using the same number as the threshold for the entire image . This method is not suitable for all situations, especially when different parts of the same image have different brightness. In this case we need to use an adaptive threshold . The threshold at this time is to calculate the corresponding threshold based on each small area on the image. Therefore, different thresholds are used in different areas of the same image , allowing us to get better results when the brightness is different.

adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)**
 This method requires us to specify six parameters and only returns one value.

 • **Adaptive Method**—Specifies the method used to calculate the threshold.
 – **cv2.ADPTIVE_THRESH_MEAN_C**: The threshold is taken from the average value of adjacent areas
 – **cv2.ADPTIVE_THRESH_GAUSSIAN_C**: The threshold is taken from the weighted sum of adjacent areas, and the weight is a Gaussian window. 
 • **Block Size** - Neighborhood size (size of the region used to calculate the threshold).
 • **C** - This is a constant and the threshold is equal to the average or weighted average minus this constant.

# 因为光线问题, 全局二值化导致有部分地方看不见了.这时就需要自适应阈值二值化了.
import cv2
import numpy as np

img = cv2.imread('./math.png')

cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 1920, 1080)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 自适应阈值二值化只返回一个值, 即二值化后的结果
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 3, 0)

cv2.imshow('img', np.hstack((gray, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 

1.3 Corrosion operations

 The corrosion operation also uses a convolution kernel to scan the image, but the convolution kernel of the corrosion operation is generally 1. If all pixels in the convolution kernel are white, then the anchor point is white. 

- Most of the time, the corrosion operation uses a convolution kernel of all 1.

- erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

  - iterations is the number of iterations of the corrosion operation. The greater the number, the more times the corrosion operation is performed, and the more obvious the corrosion effect is.

import cv2
import numpy as np

img = cv2.imread('./msb.png')

kernel = np.ones((3, 3), np.uint8)

dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

1.4 Obtain morphological convolution kernel

- opencv provides an API for obtaining convolution kernels. We do not need to manually create convolution kernels.
- getStructuringElement(shape, ksize[, anchor])

  - Shape refers to the shape of the convolution kernel. Note that it does not refer to the length and width, but refers to the shape formed by the 1 in the convolution kernel.
    - MORPH_RECT The 1 in the convolution kernel is a rectangle, which is commonly used.
    - MORPH_ELLIPSE ellipse
    - MORPH_CROSS cross

import cv2
import numpy as np

img = cv2.imread('./j.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

1.5 Expansion operation

Dilation is the opposite operation of erosion. The basic principle is that as long as the anchor point of the convolution kernel is guaranteed to be a non-zero value, the surrounding values ​​will become non-zero values, whether they are 0 or non-zero values.

- dilate(img, kernel, iterations=1)

import cv2
import numpy as np

img = cv2.imread('./j.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.dilate(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 

1.6 Open operation

 Opening and closing operations are both basic applications of erosion and dilation. 

- Open operation = erosion + expansion
- morphologyEx(img, MORPH_OPEN, kernel)

  - MORPH_OPEN represents the morphological opening operation
  - kernel If there are more noise points, a larger kernel will be selected. If the noise points are smaller, a smaller kernel can be selected.

import cv2
import numpy as np

img = cv2.imread('./dotj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 腐蚀
# dst = cv2.erode(img, kernel, iterations=2)

# # 膨胀
# dst = cv2.dilate(dst, kernel, iterations=2)

# 直接调用opencv提供的开运算api
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

1.7 Closed operations

- Closed operation = dilation + erosion

import cv2
import numpy as np

img = cv2.imread('./dotinj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

1.8 Morphological gradient

- Gradient = Original image - Corrosion
- After corrosion, the edge of the original image becomes smaller. Original image - Corrosion can get the corroded part, that is, the edge.

import cv2
import numpy as np

img = cv2.imread('./j.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

1.9 Top hat operation

- Top hat = original image - Open operation
- The effect of Open operation is to remove noise outside the image. Original image - Open operation will get the removed noise.

import cv2
import numpy as np

img = cv2.imread('./tophat.png')

# 注意调整kernel以保留小图形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (19, 19))

dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 

1.10 Black hat operation

- Black hat = original image - closed operation
- closed operation can remove the noise inside the graphic, then the result of the original image - closed operation is the noise inside the graphic.

import cv2
import numpy as np

img = cv2.imread('./dotinj.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

Guess you like

Origin blog.csdn.net/peng_258/article/details/132774908