Image processing 006_Image gradient in OpenCV

The main content of this article comes from the image processing part of OpenCV in the OpenCV-Python tutorial . The main content of this part is as follows:

Target

In this chapter we will learn:

theory

OpenCV provides three types of gradient filters or high-pass filters, Sobel, Scharr and Laplacian. We'll look at each of them.

1. Sobel and Scharr derivatives

The Sobel operator is a combined Gaussian smoothing plus differential operation, so it has stronger noise resistance. We can specify the direction of the derivative to be taken, vertical or horizontal (via the parameters yorderand respectively xorder). You can also ksizespecify the kernel size via parameters. If ksize = -1, then a 3x3 Scharr filter will be used, which gives better results than a 3x3 Sobel filter. Please refer to the documentation for the kernel you are using.

2. Laplacian derivative

It is calculated by the relation Δ src = ∂ 2 src ∂ x 2 + ∂ 2 src ∂ y 2 \Delta src = \frac{\partial ^2{src}}{\partial x^2} + \frac{\partial ^2 {src}}{\partial y^2}Δsrc=x22src+y22srcThe Laplacian of the given image, where each derivative is found using the Sobel derivative. If ksize = 1, the following kernel will be used for filtering
kernel = [ 0 1 0 1 − 4 1 0 1 0 ] kernel = \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix}kernel=010141010

code

The code below shows all these operations in one picture. All cores are 5x5 in size. Pass -1 for the depth of the output image to get np.uint8results of type .

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

def image_gradients():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('sudoku.png'), 0)
    print(img.shape)
    img = cv.resize(img, (359, 361))
    laplacian = cv.Laplacian(img, cv.CV_64F)
    sobelx = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
    sobely = cv.Sobel(img, cv.CV_64F, 0, 1, ksize=5)

    cv.imshow("Original", img)
    cv.imshow("Laplacian", laplacian)
    cv.imshow("Sobel X", sobelx)
    cv.imshow("Sobel Y", sobely)

    cv.waitKey(-1)
    cv.destroyAllWindows()


if __name__ == "__main__":
    image_gradients()

The results are as follows:
[The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-qZrKoTJl-1651362541111)(https://upload-images.jianshu.io/upload_images/1315506- 5e604eab748f2c88.png)]

an important question

In our previous example, the output data type was cv.CV_8Uor np.uint8. But there's a small problem. A black to white transition is considered a positive slope (it has a positive value), while a white to black transition is considered a negative slope (it has a negative value). So when you convert the data to np.uint8, all negative slopes are set to 0. Simply put, the edge is lost.

If we want to detect two edges, a better option is to keep the output data type to some higher form, like cv.CV_16S, cv.CV_64Fetc., take its absolute value and then convert it back cv.CV_8U. The code below demonstrates this process and the difference in results for a horizontal Sobel filter.

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

def image_gradients2():
    img = np.zeros((600, 600))
    cv.rectangle(img, (150, 100), (450, 500), (255), -1)

    # Output dtype = cv.CV_8U
    sobelx8u = cv.Sobel(img, cv.CV_8U, 1, 0, ksize=5)

    # Output dtype = cv.CV_64F. Then take its absolute and convert to cv.CV_8U
    sobelx64f = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
    abs_sobel64f = np.absolute(sobelx64f)
    sobel_8u = np.uint8(abs_sobel64f)

    plt.subplot(1, 3, 1), plt.imshow(img, cmap='gray')
    plt.title('Original'), plt.xticks([]), plt.yticks([])
    plt.subplot(1, 3, 2), plt.imshow(sobelx8u, cmap='gray')
    plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
    plt.subplot(1, 3, 3), plt.imshow(sobel_8u, cmap='gray')
    plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])

    plt.show()


if __name__ == "__main__":
    image_gradients2()

The inspection results are as follows:
Image

Other resources

practise

Reference documentation

Image Gradients

Done.

Guess you like

Origin blog.csdn.net/tq08g2z/article/details/124522388