Opencv - python quick start

Opencv - python

1. IO operation of image

1.1 reading images

1.API

cv.imread()

Parameters:

  • Image to read

  • Flag of reading mode

    • cv.IMREAD*COLOR: load the image in color mode, and the transparency of any image will be ignored. This is the default parameter.

    • cv.IMREAD*GRAYSCALE: load the image in grayscale mode

    • cv.IMREAD_UNCHANGED: load image mode including alpha channel.

      You can use 1, 0, or - 1 instead of the above three flags

  • Reference code

    import numpy as np
    import cv2 as cv
    # Read the image in the form of grayscale image
    img = cv.imread('messi5.jpg',0)
    

Note: if there is an error in the loaded path, no error will be reported, and a None value will be returned

1.2 display image

1 . API

cv.imshow()

Parameters:

  • The name of the window that displays the image, expressed as a string
  • Image to load

Note: after calling the API for displaying the image, call cv.waitKey() to leave time for the image drawing, otherwise the window will have no response and the image cannot be displayed.

In addition, we can also use matplotlib to display images.

  1. Reference code

    # Display in opencv
    cv.imshow('image',img)
    cv.waitKey(0)
    # Displayed in matplotlib
    plt.imshow(img[:,:,::-1])
    

1.3 saving images

  1. API

    cv.imwrite()
    

    Parameters:

    • File name, where do you want to save it
    • Image to save
  2. Reference code

    cv.imwrite('messigray.png',img)
    

    1.4 summary

    We load the grayscale image and display the image. If we press's' and exit, we will save the image, or press ESC to exit without saving.

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1 read image
    img = cv.imread('messi5.jpg',0)
    # 2 display image
    # 2.1 displaying images with opencv
    cv.imshow('image',img)
    # 2.2 displaying images in Matplotlib
    plt.imshow(img[:,:,::-1])
    plt.title('Matching results'), plt.xticks([]), plt.yticks([])
    plt.show()
    k = cv.waitKey(0)
    # 3 save image
    cv.imwrite('messigray.png',img)
    

2 drawing geometry

2.1 draw a straight line

cv.line(img,start,end,color,thickness)

Parameters:

  • img: image to draw a line
  • Start,end: start and end of the line
  • Color: the color of the line
  • Thickness: line width

2.2 draw a circle

cv.circle(img,centerpoint, r, color, thickness)

Parameters:

  • img: image to draw a circle
  • Centerpoint, r: Center and radius
  • Color: the color of the line
  • Thickness: the width of the line. When it is - 1, a closed pattern is generated and filled with color

2.3 draw rectangle

cv.rectangle(img,leftupper,rightdown,color,thickness)

Parameters:

  • img: image to draw rectangle
  • Leftupper, rightdown: coordinates of the upper left and lower right corners of the rectangle
  • Color: the color of the line
  • Thickness: line width

2.4 adding text to images

cv.putText(img,text,station, font, fontsize,color,thickness,cv.LINE_AA)

Parameters:

  • img: image
  • Text: text data to write
  • station: where text is placed
  • Font: font
  • Font size: font size

2.5 effect display

We generate an all black image, then draw the image and add text in it

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 create a blank image
img = np.zeros((512,512,3), np.uint8)
# 2 drawing graphics
cv.line(img,(0,0),(511,511),(255,0,0),5)
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
cv.circle(img,(447,63), 63, (0,0,255), -1)
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)
# 3 image display
plt.imshow(img[:,:,::-1])
plt.title('Matching results'), plt.xticks([]), plt.yticks([])
plt.show()

3. Image attribute operation

3.1 acquire and modify pixels in the image

We can obtain the pixel value of the pixel point through the coordinate values of the row and column. For BGR images, it returns an array of blue, green, and red values. For grayscale images, only the corresponding intensity value is returned. Use the same method to modify the pixel value.

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
# Gets the value of a pixel
px = img[100,100]
# Gets only the intensity value of the blue channel
blue = img[100,100,0]
# Modify the pixel value of a location
img[100,100] = [255,255,255]

3.2 acquiring image attributes

Image attributes include the number of rows, columns and channels, image data type, number of pixels, etc.

3.3 splitting and merging of image channels

Sometimes it is necessary to work alone on B, G and R channel images. In this case, the BGR image needs to be divided into a single channel. Or in other cases, it may be necessary to combine these separate channels into BGR images. You can do it in the following ways.

# Channel splitting
b,g,r = cv.split(img)
# Channel merging
img = cv.merge((b,g,r))

3.4 change of color space

There are more than 150 color space conversion methods in OpenCV. There are two most widely used conversion methods, BGR ↔ Gray and BGR ↔ HSV.

API:

cv.cvtColor(input_image,flag)

Parameters:

  • input_image: image for color space conversion
  • flag: conversion type
    • cv.COLOR_BGR2GRAY : BGR↔Gray
    • cv.COLOR_BGR2HSV: BGR→HSV

Summary:

  1. API for image IO operations:

    cv.imread(): read image

    cv.imshow(): display image

    cv.imwrite(): save image

  2. Draw a geometric image on the image

    cv.line(): draw a line

    cv.circle(): draw a circle

    cv.rectangle(): draw a rectangle

    cv.putText(): add text to the image

  3. Directly use the row and column index to obtain and modify the pixels in the image

  4. Image properties

  5. Split channel: cv.split()

    Channel merge: cv.merge()

  6. Change of color space

    cv.cvtColor(input_image,flag)

4. Arithmetic operation

Learning objectives

  • Understand the addition and mixing of images

4.1 image addition

You can add two images using OpenCV's cv.add() function, or you can simply add two images through numpy operation, such as res = img1 + img2. The two images should have the same size and type, or the second image can be a scalar value.

Note: there is a difference between OpenCV addition and Numpy addition. OpenCV addition is a saturation operation, while Numpy addition is a modular operation.

Refer to the following codes:

>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y )          # 250+10 = 260 % 256 = 4
[4]

This difference is more obvious when you add two images. The result of OpenCV will be better. So we try to use the functions in OpenCV.

code:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# 1 read image
img1 = cv.imread("view.jpg")
img2 = cv.imread("rain.jpg")

# 2 addition operation
img3 = cv.add(img1,img2) # Addition in cv
img4 = img1+img2 # Direct addition

# 3 image display
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img3[:,:,::-1])
axes[0].set_title("cv Addition in")
axes[1].imshow(img4[:,:,::-1])
axes[1].set_title("Direct addition")
plt.show()

4.2 image blending

This is actually addition, but the difference is that the weights of the two images are different, which will give people a feeling of mixing or transparency. The calculation formula of image blending is as follows:

g(x) = (1−α)f0(x) + αf1(x)

Through modification α The value of (0 → 1) can achieve very cool mixing.

Now let's mix the two pictures together. The weight of the first picture is 0.7 and the weight of the second picture is 0.3. The function * * cv2.addWeighted() * * can mix pictures according to the following formula.

dst = α⋅img1 + β⋅img2 + γ

here γ Take zero.

addWeighted()

Refer to the following codes:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# 1 read image
img1 = cv.imread("view.jpg")
img2 = cv.imread("rain.jpg")

# 2 image blending
img3 = cv.addWeighted(img1,0.7,img2,0.3,0)

# 3 image display
plt.figure(figsize=(8,8))
plt.imshow(img3[:,:,::-1])
plt.show()

summary

  1. Image addition: load two images together

    cv.add()

  2. Image mixing: mix the two images in different proportions

    cv.addweight()

Note: both images are required to be of the same size.

5. Image processing

  • Geometric transformation of image
  • Morphological transformation of image
  • Image smoothing method
  • Histogram method
  • Edge detection method
  • Application of template matching and Hough transform

5.1 image geometric transformation

5.1.1 image scaling

Zoom is to adjust the size of the image, even if the image is enlarged or reduced.

  1. API

    cv2.resize(src,dsize,fx=0,fy=0,interpolation=cv2.INTER_LINEAR)
    

    Parameters:

    • src: input image

    • dsize: absolute size, which directly specifies the size of the adjusted image

    • fx,fy: relative size, set dsize to None, and then set fx and fy as scale factors

    • Interpolation: interpolation method,

  2. import cv2 as cv
    # 1. Read pictures
    img1 = cv.imread("./image/dog.jpeg")
    # 2. Image scaling
    # 2.1 absolute dimensions
    rows,cols = img1.shape[:2]
    res = cv.resize(img1,(2*cols,2*rows),interpolation=cv.INTER_CUBIC)
    
    # 2.2 relative dimensions
    res1 = cv.resize(img1,None,fx=0.5,fy=0.5)
    
    # 3 image display
    # 3.1 using opencv to display images (not recommended)
    cv.imshow("orignal",img1)
    cv.imshow("enlarge",res)
    cv.imshow("shrink)",res1)
    cv.waitKey(0)
    
    # 3.2 displaying images using matplotlib
    fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
    axes[0].imshow(res[:,:,::-1])
    axes[0].set_title("Absolute scale (enlarged)")
    axes[1].imshow(img1[:,:,::-1])
    axes[1].set_title("Original drawing")
    axes[2].imshow(res1[:,:,::-1])
    axes[2].set_title("Relative scale (reduction)")
    plt.show()
    

5.1.2 image translation

Image pan moves the image to the corresponding position according to the specified direction and distance.

  1. API
cv.warpAffine(img,M,dsize)

Parameters:

  • img: input image

  • M: 2 * * 3 moving matrix

    Note: set MM to a Numpy array of type np.float32.

  • dsize: the size of the output image

    Note: the size of the output image should be in the form of (width, height). Remember, width = number of columns, height = number of rows.

  • Example

The requirement is to move (50100) the pixels of the image:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1. Read image
img1 = cv.imread("./image/image2.jpg")

# 2. Image translation
rows,cols = img1.shape[:2]
M = M = np.float32([[1,0,100],[0,1,50]])# translation matrix 
dst = cv.warpAffine(img1,M,(cols,rows))

# 3. Image display
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("Original drawing")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("Result after translation")
plt.show()

5.3 image rotation

  1. API

    cv2.getRotationMatrix2D(center, angle, scale)
    

    Parameters:

    • Center: rotation center
    • Angle: rotation angle
    • Scale: scale

    return:

    • M: Rotation matrix

      Call cv.warpAffine to rotate the image

  2. Example

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1 read image
    img = cv.imread("./image/image2.jpg")
    
    # 2 image rotation
    rows,cols = img.shape[:2]
    # 2.1 generate rotation matrix
    M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
    # 2.2 perform rotation transformation
    dst = cv.warpAffine(img,M,(cols,rows))
    
    # 3 image display
    fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
    axes[0].imshow(img1[:,:,::-1])
    axes[0].set_title("Original drawing")
    axes[1].imshow(dst[:,:,::-1])
    axes[1].set_title("Results after rotation")
    plt.show()
    

5.1.3 affine transformation

Affine transformation of image involves the change of shape, position and angle of image, which is a common function in deep learning preprocessing. Affine transformation is mainly a combination of image scaling, rotation, flipping and translation.

What is the affine transformation of the image? As shown in the figure below, points 1, 2 and 3 in Figure 1 are mapped one by one with the three points in Figure 2, and still form a triangle, but the shape has changed greatly. In this way, the affine transformation is obtained through two groups of three points (points of interest). Next, we can apply the affine transformation to all points in the image to complete the affine transformation of the image.

In affine transformation, all parallel lines in the original image are also parallel in the resulting image. To create this matrix, we need to find three points from the original image and their positions in the output image. Then cv2.getA "neTransform will create a 2x3 matrix, and finally this matrix will be passed to the function cv2.warpA" ne.

Example

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 image reading
img = cv.imread("./image/image2.jpg")

# 2 affine transformation
rows,cols = img.shape[:2]
# 2.1 create transformation matrix
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[100,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
# 2.2 complete affine transformation
dst = cv.warpAffine(img,M,(cols,rows))

# 3 image display
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title("Original drawing")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("Affine result")
plt.show()

5.1.4 transmission transformation

Transmission transformation is the result of the change of viewing angle. It refers to the transformation that uses the condition that the perspective center, image point and target point are collinear, rotates the background surface (perspective surface) around the trace (perspective axis) by a certain angle according to the perspective rotation law, destroys the original projection beam, and can still keep the projection geometry on the background surface unchanged.

In opencv, we need to find four points, of which any three are not collinear, and then obtain the transformation matrix T, and then carry out the transmission transformation. Find the transformation matrix through the function cv.getPerspectiveTransform, and apply cv.warmperspective to this 3x3 transformation matrix.

  1. Example

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1 read image
    img = cv.imread("./image/image2.jpg")
    # 2 transmission transformation
    rows,cols = img.shape[:2]
    # 2.1 create transformation matrix
    pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
    pts2 = np.float32([[100,145],[300,100],[80,290],[310,300]])
    
    T = cv.getPerspectiveTransform(pts1,pts2)
    # 2.2 transformation
    dst = cv.warpPerspective(img,T,(cols,rows))
    
    # 3 image display
    fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
    axes[0].imshow(img[:,:,::-1])
    axes[0].set_title("Original drawing")
    axes[1].imshow(dst[:,:,::-1])
    axes[1].set_title("Post transmission results")
    plt.show()
    

5.1.5 image pyramid

Image pyramid is a kind of multi-scale representation of image. It is mainly used for image segmentation. It is an effective but simple structure to interpret image with multi-resolution.

Image pyramid is used for machine vision and image compression. The pyramid of an image is a series of images arranged in the shape of a pyramid, with gradually reduced resolution and derived from the same original image. It is obtained by step down sampling, and the sampling is not stopped until a certain termination condition is reached.

The bottom of the pyramid is a high-resolution representation of the image to be processed, while the top is a low-resolution approximation. The higher the level, the smaller the image and the lower the resolution.

  1. API

    cv.pyrUp(img)       #Up sampling the image
    cv.pyrDown(img)        #Down sampling the image
    
  2. Example

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1 image reading
    img = cv.imread("./image/image2.jpg")
    # 2 image sampling
    up_img = cv.pyrUp(img)  # Up sampling operation
    img_1 = cv.pyrDown(img)  # Down sampling operation
    # 3 image display
    cv.imshow('enlarge', up_img)
    cv.imshow('original', img)
    cv.imshow('shrink', img_1)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

summary

  1. Image zoom: zooms in or out of an image

    cv.resize()

  2. Image pan:

    After the translation matrix is specified, the cv.warpAffine() translation image is called.

  3. Image rotation:

    Call cv.getRotationMatrix2D to get the rotation matrix, then call cv.warpAffine() to rotate.

  4. Affine transformation:

    Calling cv.getAffineTransform will create a transformation matrix, and finally the matrix will be passed to cv.warpAffine() for transformation

  5. Transmission Transformation:

    Find the transformation matrix through the function cv.getPerspectiveTransform(), and project cv. Warmperspective()

  6. Pyramid

    Image pyramid is a kind of image multi-scale expression. The API used is:

    cv.pyrUp(): sample up

    cv.pyrDown(): down sampling

5.2 morphological operation

Learning objectives

  • Understanding the domain of images, connectivity
  • Understand different morphological operations: corrosion, expansion, opening and closing operations, top hat and black Mao, and the relationship between different operations

Connectivity

In the image, the smallest unit is the pixel. There are 8 adjacent pixels around each pixel. There are three common adjacency relationships: 4 adjacency, 8 adjacency and D adjacency

  • 4 adjacency: the 4 neighborhood of pixel p(x,y) is: (x+1,y); (x-1,y); (x,y+1); (x,y-1), N_4 § N4(p) indicates the 4 adjacency of pixel p
  • D adjacency: the D neighborhood of pixel p(x,y) is: the point on the diagonal (x+1,y+1); (x+1,y-1); (x-1,y+1); (x-1,y-1), N_D § N**D(p) represents the D neighborhood of pixel p
  • 8 adjacency: the 8 neighborhood of pixel p(x,y) is: the point of 4 neighborhood + the point of D neighborhood, with N_{8} § N8(p) represents the 8 neighborhood of pixel p

Connectivity is an important concept for describing regions and boundaries. The two necessary conditions for the connectivity of two pixels are:

  1. Are the positions of the two pixels adjacent
  2. Whether the gray values of the two pixels meet the specific similarity criteria (or whether they are equal)

According to the definition of connectivity, there are three types: 4 Unicom, 8 Unicom and m Unicom.

  • 4 connection: for the pixels pp and qq with the value VV, if qq is in the set N_4 § N4(p), the two pixels are said to be 4 connected.
  • 8 connection: for the pixels pp and qq with the value VV, if qq is in the set N_8 § N8(p), the two pixels are said to be 8 connected.

5.2.1 corrosion and expansion

Introduction:

  • Corrosion and expansion are the most basic morphological operations. Both corrosion and expansion are for the white part (highlighted part).

  • Expansion is to expand the highlighted part in the image, and the effect image has a larger highlighted area than the original image; corrosion is that the highlighted area in the original image is eroded, and the effect image has a smaller highlighted area than the original image. Expansion is the operation of finding the local maximum value, and corrosion is the operation of finding the local minimum value.

  • The function of corrosion is to eliminate the boundary points of the object, reduce the target, and eliminate the noise points smaller than the structural elements.

API:

   cv.erode(img,kernel,iterations)

Parameters:

  • img: image to process

  • kernel: core structure

  • iterations: corrosion times. The default value is 1

  • Expansion is to merge all the background points in contact with the object into the object to increase the target and supplement the holes in the target.

API:

   cv.dilate(img,kernel,iterations)

Parameters:

  • img: image to process
  • kernel: core structure
  • iterations: corrosion times. The default value is 1

We use a convolution kernel of 5 * 5 to realize the operation of corrosion and expansion:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 read image
img = cv.imread("./image/image3.png")
# 2 create core structure
kernel = np.ones((5, 5), np.uint8)

# 3 image corrosion and expansion
erosion = cv.erode(img, kernel) # corrosion
dilate = cv.dilate(img,kernel) # expand

# 4 image display
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(img)
axes[0].set_title("Original drawing")
axes[1].imshow(erosion)
axes[1].set_title("Results after corrosion")
axes[2].imshow(dilate)
axes[2].set_title("Results after expansion")
plt.show()

5.2.2 opening and closing operation

The open and close operations deal with corrosion and expansion in a certain order, but they are not reversible, that is, opening first and then closing can not get the original image.

  1. Open operation

    The operation is to corrode first and then expand. Its function is to separate objects and eliminate small areas== Features: eliminate noise and small interference blocks without affecting the original image==

  2. Closed operation

    The closed operation is opposite to the open operation. It expands first and then corrodes. Its function is to eliminate / "close" the holes in the object. Feature: it can fill the closed area.

  3. API

    cv.morphologyEx(img, op, kernel)
    

    Parameters:

    • img: image to process
    • op: processing method: if open operation is performed, it is set to cv.MORPH_OPEN, if closed operation is performed, it is set to cv.MORPH_CLOSE
    • Kernel: core structure
  4. Example

    Implementation of opening and closing convolution using 10 * 10 kernel structure.

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1 read image
    img1 = cv.imread("./image/image5.png")
    img2 = cv.imread("./image/image6.png")
    # 2 create core structure
    kernel = np.ones((10, 10), np.uint8)
    # 3 opening and closing operation of image
    cvOpen = cv.morphologyEx(img1,cv.MORPH_OPEN,kernel) # Open operation
    cvClose = cv.morphologyEx(img2,cv.MORPH_CLOSE,kernel)# Closed operation
    # 4 image display
    fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
    axes[0,0].imshow(img1)
    axes[0,0].set_title("Original drawing")
    axes[0,1].imshow(cvOpen)
    axes[0,1].set_title("Open operation result")
    axes[1,0].imshow(img2)
    axes[1,0].set_title("Original drawing")
    axes[1,1].imshow(cvClose)
    axes[1,1].set_title("Closed operation result")
    plt.show()
    

5.2.3 top hat and black hat

  1. Top hat operation

    The difference between the original image and the result of "open operation".

    Because the result of the open operation is to enlarge the crack or local low brightness area, the effect image obtained by subtracting the opened image from the original image highlights the area brighter than the area around the contour of the original image, and this operation is related to the size of the selected core.

    The top hat operation is used to separate the patches that are lit next to each other. When an image has a large background and small objects are regular, the top hat operation can be used to extract the background.

  2. Black hat operation

    Is the difference between the result image of "closed operation" and the original image.

    The effect image after cap operation highlights the darker area than the area around the contour of the original image, and this operation is related to the size of the selected core.

    Black hat operation is used to separate patches darker than adjacent points.

  3. API

    cv.morphologyEx(img, op, kernel)
    

    Parameters:

    • img: image to process
    • op: processing method:
    • Kernel: core structure
  4. Example

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 read image
img1 = cv.imread("./image/image5.png")
img2 = cv.imread("./image/image6.png")
# 2 create core structure
kernel = np.ones((10, 10), np.uint8)
# 3 top hat and black hat operation of image
cvOpen = cv.morphologyEx(img1,cv.MORPH_TOPHAT,kernel) # Top hat operation
cvClose = cv.morphologyEx(img2,cv.MORPH_BLACKHAT,kernel)# Black hat operation
# 4 image display
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img1)
axes[0,0].set_title("Original drawing")
axes[0,1].imshow(cvOpen)
axes[0,1].set_title("Top hat calculation result")
axes[1,0].imshow(img2)
axes[1,0].set_title("Original drawing")
axes[1,1].imshow(cvClose)
axes[1,1].set_title("Black hat operation result")
plt.show()

summary

  1. Connectivity adjacency relationship: 4 adjacency, 8 adjacency and D adjacency

    Connectivity: 4-connected, 8-connected and m-connected

  2. Morphological operation

    • Corrosion and expansion:

      Corrosion: local maximum

      Expansion: find local minimum

    • Opening and closing operation:

      On: corrosion before expansion

      Closed: expansion before corrosion

    • Top hat and black hat:

      Top hat: difference between original image and operation calculation

      Black hat: difference between closed operation and original image

5.3 image smoothing

Learning objectives

  • Understand the types of noise in the image
  • Understand average filtering, Gaussian filtering, median filtering, etc
  • The image can be processed using a filter

Image noise:

Because the process of image acquisition, processing and transmission will inevitably be polluted by noise, which hinders people's understanding, analysis and processing of images. The common image noise includes Gaussian noise, salt and pepper noise and so on.

Salt and pepper noise

Salt and pepper noise, also known as impulse noise, is a kind of noise often seen in images. It is a random white dot or black dot. It may be that there are black pixels in bright areas or white pixels in dark areas (or both) . salt and pepper noise may be caused by sudden strong interference of image signal, analog-to-digital converter or bit transmission error, etc. for example, the pixel value is the minimum value caused by a failed sensor, and the pixel value is the maximum value caused by a saturated sensor.

Gaussian noise

Gaussian noise is a kind of noise whose noise density function obeys Gaussian distribution. Due to the mathematical ease of Gaussian noise in space and frequency domain, this noise (also known as normal noise) model is often used in practice.

5.3.1 mean filtering

The average filtering template is used to filter out the image noise. If the [external chain picture fails to be transferred, the source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-7m7by28n-1637649744832)( https://math.jianshu.com/math?formula=S_%7Bx%20y%7D )]Indicates that the center is at point (x, y) and the dimension is m × The coordinate group of the rectangular sub image window of n.

It is completed by a normalized convolution frame. It only uses the average value of all pixels in the coverage area of the convolution frame to replace the central element.

  • The advantage of mean filtering is that the algorithm is simple and the calculation speed is fast. The disadvantage is that many details are removed while denoising, which makes the image blurred.

API:

cv.blur(src, ksize, anchor, borderType)

Parameters:

  • src: input image
  • ksize: size of convolution kernel
  • anchor: the default value (- 1, - 1) indicates the core center
  • borderType: boundary type

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 image reading
img = cv.imread('./image/dogsp.jpeg')
# 2 mean filtering
blur = cv.blur(img,(5,5))
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('Mean filtered results')
plt.xticks([]), plt.yticks([])
plt.show()

5.3.2 Gaussian filtering

Two dimensional Gaussian filter is the basis of constructing Gaussian filter

API:

cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)

Parameters:

  • src: input image
  • ksize: the size of Gaussian convolution kernel. Note: the width and height of convolution kernel should be odd and can be different
  • Sigma X: standard deviation in horizontal direction
  • Sigma: the standard deviation in the vertical direction. The default value is 0, which means it is the same as sigma X
  • borderType: fill boundary type

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 image reading
img = cv.imread('./image/dogGasuss.jpeg')
# 2 Gaussian filtering
blur = cv.GaussianBlur(img,(3,3),1)
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('Results after Gaussian filtering')
plt.xticks([]), plt.yticks([])
plt.show()

5.3.3 median filtering

Median filtering is a typical nonlinear filtering technology. The basic idea is to replace the gray value of the pixel with the median of the gray value in the neighborhood of the pixel.

Median filtering is particularly useful for salt and pepper noise because it does not depend on the values in the neighborhood that are very different from the typical values.

API:

cv.medianBlur(src, ksize )

Parameters:

  • src: input image
  • ksize: size of convolution kernel

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 image reading
img = cv.imread('./image/dogsp.jpeg')
# 2-value filtering
blur = cv.medianBlur(img,5)
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('Results after median filtering')
plt.xticks([]), plt.yticks([])
plt.show()

summary

  1. Image noise

    • Salt and pepper noise: random white or black spots in an image
    • Gaussian noise: the probability density distribution of noise is normal
  2. Image smoothing

    • Mean filtering: the algorithm is simple and fast. It removes many details while denoising, making the image blurred

      cv.blur()

    • Gaussian filtering: removing Gaussian noise

      cv.GaussianBlur()

    • Median filtering: removing salt and pepper noise

      cv.medianBlur()

5.4 histogram

Learning objectives

  • Master the histogram calculation and display of images
  • Understand mask applications
  • Familiar with histogram equalization and adaptive equalization

Principle:

Histogram is a method to make statistics on data, and organize the statistical values into a series of bin defined by implementation. Bin is a concept often used in histogram, which can be translated as "straight bar" or "group distance" , whose values are feature statistics calculated from data, such as gradient, direction, color or any other feature.

Image Histogram is a histogram used to represent the brightness distribution in a digital image. It plots the number of pixels of each brightness value in the image. In this histogram, the left side of the abscissa is a darker area and the right side is a brighter area. Therefore, the data in the histogram of a darker image is mostly concentrated in the left and middle parts, while the image with overall brightness and only a small amount of shadow is the opposite.

Some terms and details of histogram:

  • Dims: the number of features to be counted. In the above example, dims = 1 because only gray values are counted.
  • Bins: the number of sub segments of each feature space, which can be translated as "straight bar" or "group distance". In the above example, bins = 16.
  • Range: the value range of the feature to be counted. In the above example, range = [0, 255].

Significance of histogram:

  • Histogram is a graphical representation of pixel intensity distribution in an image.
  • It counts the number of pixels for each intensity value.
  • The histograms of different images may be the same

5.4.1 calculation and drawing of histogram

We use the method in OpenCV to count the histogram and draw it with matplotlib.

API:

cv2.calcHist(images,channels,mask,histSize,ranges[,hist[,accumulate]])

Parameters:

  • images: original image. When a function is passed in, it should be enclosed in brackets [], for example: [img].
  • Channels: if the input image is a grayscale image, its value is [0]; If it is a color image, the input parameters can be [0], [1], [2], which correspond to channels B, G and R respectively.
  • Mask: mask image. To count the histogram of the whole image, set it to None. But if you want to count the histogram of a part of the image, you need to make a mask image and use it. (examples follow)
  • Histsize: number of bin. It should also be enclosed in square brackets, for example: [256].
  • ranges: pixel value range, usually [0256]

Example:

As shown in the figure below, draw the corresponding histogram

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1 read directly in the form of gray image
img = cv.imread('./image/cat.jpeg',0)
# 2 Statistical grayscale image
histr = cv.calcHist([img],[0],None,[256],[0,256])
# 3 draw grayscale map
plt.figure(figsize=(10,6),dpi=100)
plt.plot(histr)
plt.grid()
plt.show()

5.4.2 mask application

Mask is to block the image to be processed with the selected image, figure or object to control the area of image processing.

In digital image processing, we usually use two-dimensional matrix array for mask. The mask is a binary image composed of 0 and 1. The mask image is used to mask the image to be processed, in which the 1 value area is processed, and the 0 value area is shielded and will not be processed.

The main uses of the mask are:

  • Extracting region of interest: perform "and" operations with the pre-made region of interest mask and the image to be processed to obtain the region of interest image. The image value in the region of interest remains unchanged, while the image value outside the region of interest is 0.
  • Shielding function: mask some areas on the image so that they do not participate in processing or calculation of processing parameters, or only process or count the shielding area.
  • Structural feature extraction: the structural features similar to the mask in the image are detected and extracted by similarity variable or image matching method.
  • Special shape image making

Mask is widely used in remote sensing image processing. When extracting roads, rivers or houses, a mask matrix is used to filter the pixels of the image, and then the features or signs we need are highlighted.

We use * * cv.calcHist() * * to find the histogram of the complete image. What should we do if we want to find the histogram of some areas of the image? Just create a white mask image on the area where we want to find the histogram, otherwise create black, and then pass it as a mask mask.

Example:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1. Read directly in the form of gray image
img = cv.imread('./image/cat.jpeg',0)
# 2. Create mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[400:650, 200:500] = 255
# 3. Mask
masked_img = cv.bitwise_and(img,img,mask = mask)
# 4. Count the gray image of the image after the mask
mask_histr = cv.calcHist([img],[0],mask,[256],[1,256])
# 5. Image display
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img,cmap=plt.cm.gray)
axes[0,0].set_title("Original drawing")
axes[0,1].imshow(mask,cmap=plt.cm.gray)
axes[0,1].set_title("Mask data")
axes[1,0].imshow(masked_img,cmap=plt.cm.gray)
axes[1,0].set_title("Post mask data")
axes[1,1].plot(mask_histr)
axes[1,1].grid()
axes[1,1].set_title("Gray histogram")
plt.show()

5.4.3 histogram homogenization

Principle:

  • Histogram equalization "is to change the gray histogram of the original image from a relatively concentrated gray interval to a distribution in a wider gray range. Histogram equalization is to stretch the image nonlinearly and redistribute the image pixel values so that the number of pixels in a certain gray range is roughly the same.
  • This method improves the overall contrast of the image, especially when the pixel value distribution of useful data is close, it is widely used in X-ray images, which can improve the display of skeleton structure. In addition, it can better highlight details in overexposed or underexposed images.

When using opencv for histogram statistics, the following are used:

API:

dst = cv.equalizeHist(img)

Parameters:

  • img: grayscale image

return:

  • dst: results after equalization

Example:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1. Read directly in the form of gray image
img = cv.imread('./image/cat.jpeg',0)
# 2. Equalization treatment
dst = cv.equalizeHist(img)
# 3. Result display
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("Original drawing")
axes[1].imshow(dst,cmap=plt.cm.gray)
axes[1].set_title("Results after equalization")
plt.show()
5.4.3.1 adaptive histogram homogenization

For the above histogram equalization, we consider the global contrast of the image. Indeed, after histogram equalization, the contrast of the picture background is changed. It is too dark in the cat leg, and we lose a lot of information. Therefore, in many cases, the effect is not good. As shown in the figure below, we lost a lot of information due to the brightness of the statue in the next two images.

In order to solve this problem, adaptive histogram equalization is needed. At this time, the whole image will be divided into many small blocks, which are called "tiles" (the default size of tiles in OpenCV is 8x8), and then histogram equalization will be carried out for each small block. Therefore, in each region, the histogram will be concentrated in a small region). If there is noise, the noise will be amplified. To avoid this, use contrast limits. For each small block, if the bin in the histogram exceeds the upper limit of contrast, the pixels in the histogram are evenly dispersed into other bins, and then histogram equalization is carried out.

API:

cv.createCLAHE(clipLimit, tileGridSize)

Parameters:

  • clipLimit: contrast limit. The default value is 40
  • tileGridSize: block size. The default value is 8 * 88 * 8

Example:

import numpy as np
import cv2 as cv
# 1. Read the image in the form of grayscale image
img = cv.imread('./image/cat.jpeg',0)
# 2. Create an adaptive equalization object and apply it to the image
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
# 3. Image display
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("Original drawing")
axes[1].imshow(cl1,cmap=plt.cm.gray)
axes[1].set_title("Results after adaptive equalization")
plt.show()

summary

  1. Gray histogram:

    • Histogram is a graphical representation of pixel intensity distribution in an image.
    • It counts the number of pixels for each intensity value.
    • The histograms of different images may be the same

    cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])

  2. Mask

    Create a mask and pass it through the mask to obtain the histogram of the region of interest

  3. Histogram equalization: a method to enhance image contrast

    cv.equalizeHist(): the input is a grayscale image and the output is a histogram equalization image

  4. Adaptive histogram equalization

    The whole image is divided into many small blocks, and then each small block is histogram equalized, and finally spliced

    clahe = cv.createCLAHE(clipLimit, tileGridSize)

    5.5 edge detection

    Learning objectives

    • Understand Sobel operator, Scharr operator and Laplace operator

      Master the principle and application of canny edge detection

Edge detection is a basic problem in image processing and computer vision. The purpose of edge detection is to identify the points with obvious brightness change in digital image. Significant changes in image attributes usually reflect important events and changes in attributes.

Image edge detection greatly reduces the amount of data, eliminates the information that can be considered irrelevant, and retains the important structural attributes of the image. There are many methods for edge detection, most of which can be divided into two categories: search based and zero crossing based.

  • Based on search: detect the boundary by finding the maximum value in the first derivative of the image, and then use the calculation results to estimate the local direction of the edge. Usually, the direction of the gradient is used, and the maximum value of the local gradient module is found by using this direction. The representative algorithms are Sobel operator and Scharr operator.

5.5.1 Sobel operator

Sobel edge detection algorithm is relatively simple. In practical application, the efficiency is higher than Canny edge detection, but the edge is not as accurate as Canny edge detection. However, in many practical applications, Sobel edge is the first choice. Sobel operator is a combination of Gaussian smoothing and differential operation, so it has strong anti noise ability and many uses. Especially when the efficiency requirement is high and the fine texture is not concerned.

The API for sobel edge detection using OpenCV is:

Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)

Parameters:

  • src: incoming image

  • ddepth: depth of image

  • dx and dy: refers to the order of derivation. 0 means that there is no derivation in this direction. The values are 0 and 1.

  • ksize: is the size of Sobel operator, that is, the size of convolution kernel. It must be odd numbers 1, 3, 5 and 7. The default is 3.

    Note: if ksize=-1, it will evolve into a 3x3 Scharr operator.

  • scale: the scaling constant of the scaling derivative. By default, there is no scaling factor.

  • borderType: the mode of image boundary. The default value is cv2.BORDER_DEFAULT.

After the derivative of Sobel function is calculated, there will be negative values and values greater than 255. The original image is uint8, that is, the 8-bit unsigned number, so the image number established by Sobel is not enough and will be truncated. Therefore, use the 16 bit signed data type, cv2.CV_16S. After processing the image, use the cv2.convertScaleAbs() function to return it to the original uint8 format, otherwise the image cannot be displayed.

Sobel operator is calculated in two directions. Finally, it needs to be combined with cv2.addWeighted() function

Scale_abs = cv2.convertScaleAbs(x)  # Format conversion function
result = cv2.addWeighted(src1, alpha, src2, beta) # Image blending

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 read image
img = cv.imread('./image/horse.jpg',0)
# 2 calculate Sobel convolution results
x = cv.Sobel(img, cv.CV_16S, 1, 0)
y = cv.Sobel(img, cv.CV_16S, 0, 1)
# 3 convert data
Scale_absX = cv.convertScaleAbs(x)  # convert scale
Scale_absY = cv.convertScaleAbs(y)
# 4 Result synthesis
result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# 5 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(result,cmap = plt.cm.gray),plt.title('Sobel Filtered results')
plt.xticks([]), plt.yticks([])
plt.show()

Setting ksize to - 1 in the part of calculating sobel operator in the above code is to use Scharr for edge detection.

x = cv.Sobel(img, cv.CV_16S, 1, 0, ksize = -1)
y = cv.Sobel(img, cv.CV_16S, 0, 1, ksize = -1)

5.5.2 Laplacian operator

Laplacian uses the second derivative to detect the edge.

API:

laplacian = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])

Parameters:

  • Src: image to be processed,
  • Ddepth: depth of the image, - 1 means the same depth as the original image is used, and the depth of the target image must be greater than or equal to the depth of the original image;
  • ksize: the size of the operator, that is, the size of the convolution kernel, must be 1,3,5,7.

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 read image
img = cv.imread('./image/horse.jpg',0)
# 2 laplacian conversion
result = cv.Laplacian(img,cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(Scale_abs,cmap = plt.cm.gray),plt.title('Laplacian Post test results')
plt.xticks([]), plt.yticks([])
plt.show()

5.5.3 Canny edge detection

Canny edge detection algorithm is a very popular edge detection algorithm. It was proposed by John F. Canny in 1986 and is considered to be the optimal edge detection algorithm.

Canny edge detection algorithm consists of four steps, which are introduced as follows:

  • Step 1: noise removal

    Because edge detection is easily affected by noise, it is used first 5 ∗ 5 5*5 5 * 5 Gaussian filter to remove noise, which has been introduced in the chapter of image smoothing.

  • Step 2: calculate the image gradient

For the smoothed image, Sobel operator is used to calculate the first derivatives (Gx and Gy) in horizontal and vertical directions. According to the obtained two gradient maps (Gx and Gy), find the gradient and direction of the boundary

  • Step 3: non maximum suppression

After obtaining the direction and size of the gradient, the whole image is scanned to remove the points on the non boundary. Check each pixel to see if the gradient of this point is the largest among the surrounding points with the same gradient direction

  • Step 4: hysteresis threshold

Now we need to determine the real boundary. We set two thresholds: minVal and maxVal. When the gray gradient of the image is higher than maxVal, it is considered as the true boundary, and the boundary lower than minVal will be discarded. If it is between the two, it depends on whether this point is connected with a real boundary point. If so, it is considered to be a boundary point. If not, it is abandoned

API to implement Canny detection in OpenCV:

canny = cv2.Canny(image, threshold1, threshold2)

Parameters:

  • Image: grayscale image,
  • threshold1: minval, a smaller threshold connects discontinuous edges
  • threshold2: maxval, large threshold to detect obvious edges in the image

Example:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 image reading
img = cv.imread('./image/horse.jpg',0)
# 2 Canny edge detection
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold) 
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(canny,cmap = plt.cm.gray),plt.title('Canny Post test results')
plt.xticks([]), plt.yticks([])
plt.show()

summary

  1. Principle of edge detection

    • Search based: use the maximum value of the first derivative to obtain the boundary
    • Based on zero crossing: obtain the boundary with the second derivative of 0
  2. Sobel operator

    Search based method to obtain boundary

    cv.sobel()

    cv.convertScaleAbs()

    cv.addweights()

  3. Laplacian operator

    Boundary acquisition based on zero crossing

    cv.Laplacian()

  4. Canny algorithm

    technological process:

    • Noise removal: Gaussian filtering
    • Calculate the image gradient: sobel operator, calculate the gradient size and direction
    • Non maximum suppression: use gradient direction pixels to judge whether the current pixel is a boundary point
    • Hysteresis threshold: set two thresholds to determine the final boundary
operatorComparison of advantages and disadvantages
RobertsThe effect of image processing with steep low noise is better, but the Roberts operator is used to extract the edge. The effect of image processing with steep low noise is better, but the Roberts operator is used to extract the edge
SobelThe processing effect is better for images with gray gradient and more noise, and Sobel operator is more accurate for edge positioning.
KirschThe effect of image processing with gray gradient and more noise is better.
PrewittThe effect of image processing with gray gradient and more noise is better.
LaplacianIt can accurately locate the step edge points in the image and is very sensitive to noise. It loses the direction information of some edges, resulting in some discontinuous detection edges.
LoGLoG operator often appears double edge pixel boundary, and this detection method is sensitive to noise, so it is rarely used to detect the edge, but to judge whether the edge pixel is located in the bright or dark area of the image.
CannyThis method is not easily disturbed by noise and can detect the real weak edge. In the edge function, the most effective edge detection method is Canny method. The advantage of this method is that two different thresholds are used to detect strong edge and weak edge respectively, and the weak edge is included in the output image only when the weak edge is connected with the strong edge. Therefore, this method is not easy to be "filled" by noise, and it is easy to detect the real weak edge.
Parameters:

- image:Grayscale image,
- threshold1: minval,A smaller threshold connects the discontinuous edges
- threshold2: maxval,A larger threshold detects obvious edges in the image

Example:

```python
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 image reading
img = cv.imread('./image/horse.jpg',0)
# 2 Canny edge detection
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold) 
# 3 image display
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('Original drawing')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(canny,cmap = plt.cm.gray),plt.title('Canny Post test results')
plt.xticks([]), plt.yticks([])
plt.show()

summary

  1. Principle of edge detection

    • Search based: use the maximum value of the first derivative to obtain the boundary
    • Based on zero crossing: obtain the boundary with the second derivative of 0
  2. Sobel operator

    Search based method to obtain boundary

    cv.sobel()

    cv.convertScaleAbs()

    cv.addweights()

  3. Laplacian operator

    Boundary acquisition based on zero crossing

    cv.Laplacian()

  4. Canny algorithm

    technological process:

    • Noise removal: Gaussian filtering
    • Calculate the image gradient: sobel operator, calculate the gradient size and direction
    • Non maximum suppression: use gradient direction pixels to judge whether the current pixel is a boundary point
    • Hysteresis threshold: set two thresholds to determine the final boundary
operatorComparison of advantages and disadvantages
RobertsThe effect of image processing with steep low noise is better, but the Roberts operator is used to extract the edge. The effect of image processing with steep low noise is better, but the Roberts operator is used to extract the edge
SobelThe processing effect is better for images with gray gradient and more noise, and Sobel operator is more accurate for edge positioning.
KirschThe effect of image processing with gray gradient and more noise is better.
PrewittThe effect of image processing with gray gradient and more noise is better.
LaplacianIt can accurately locate the step edge points in the image and is very sensitive to noise. It loses the direction information of some edges, resulting in some discontinuous detection edges.
LoGLoG operator often appears double edge pixel boundary, and this detection method is sensitive to noise, so it is rarely used to detect the edge, but to judge whether the edge pixel is located in the bright or dark area of the image.
CannyThis method is not easily disturbed by noise and can detect the real weak edge. In the edge function, the most effective edge detection method is Canny method. The advantage of this method is that two different thresholds are used to detect strong edge and weak edge respectively, and the weak edge is included in the output image only when the weak edge is connected with the strong edge. Therefore, this method is not easy to be "filled" by noise, and it is easy to detect the real weak edge.

Tags: Python network udp TCP/IP

Posted on Tue, 23 Nov 2021 05:23:25 -0500 by mwichmann4