OpenCV note finishing [Sobel & Scharr & Laplacian of Image Gradient]

1. Sobel operator: Find the edge by calculating the local difference, and calculate an approximation of the gradient.

Filter (kernel): An algorithm that calculates another image from an image based on the area adjacent to the pixel (x, y). The value of the filtered target pixel is equal to the weighted sum of the original pixel and its surrounding pixels. This linear kernel-based filtering is convolution.
1. The approximate calculation formula for calculating the partial derivative in the horizontal direction
insert image description here
is: partial derivative in the horizontal direction of P5 = (P3-P1) + 2(P6-P4) + (P9-P7) Absolute value.
The calculation process is: the leftmost pixel value - the rightmost pixel value, but the weight of the middle row is the highest, multiplied by 2.

2. Calculate the approximate value of the partial derivative in the vertical direction:
the only difference from the above is: 1. The bottom pixel value - the top pixel value, the weight of the middle row is the highest, multiplied by 2.

3. Operator introduction: dst=cv2.Sobel(src,outputImgDepth,dx,dy)

Sample code: Sobel processing in X direction

import cv2

o = cv2.imread('sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,-1,1,0) # 1,0表示X方向,反之0,1表示Y方向
cv2.imshow("original",o)
cv2.imshow("x",sobelx)

cv2.waitKey()
cv2.destroyAllWindows()

Operation:
insert image description here
As you can see from the above results, only the transition edge from 255 to 0 can be calculated, but if you need to get two edges, you need to take the absolute value. To convert -255 to 255, you need to use the convertScaleAbs function to convert to an absolute value
.

import cv2

o = cv2.imread('sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
cv2.imshow("original",o)
cv2.imshow("x",sobelx)

cv2.waitKey()
cv2.destroyAllWindows()

Operation:
insert image description here
The above is only in the X direction, and the Y direction is the same, just change the order of xy in the Sobel function. But if you need to get the superimposed edges in the two directions of xy, you need to use the addWeighted function to realize the superposition.
Sample code:

import cv2

o = cv2.imread('sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0) # 先找x方向边缘
sobely = cv2.Sobel(o,cv2.CV_64F,0,1) # 再找y方向边缘
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  #叠加边缘(src1,src1Weighted,src2,src2Weighted,0)
cv2.imshow("original",o)
cv2.imshow("xy",sobelxy)
cv2.waitKey()
cv2.destroyAllWindows()

run:
insert image description here
image example:

import cv2

a=cv2.imread("./gril.png",cv2.IMREAD_GRAYSCALE)
sobel=cv2.Sobel(a,-1,1,0)

sobelx=cv2.Sobel(a,cv2.CV_64F,1,0)
sobely=cv2.Sobel(a,cv2.CV_64F,0,1)
abs_sobelx=cv2.convertScaleAbs(sobelx) 
abs_sobely=cv2.convertScaleAbs(sobely)
abs_sobelxy=cv2.addWeighted(abs_sobelx,1,abs_sobely,1,0) # 1= weighted
cv2.imshow("src",a)
cv2.imshow("abs_sobelx",abs_sobelx) 
cv2.imshow("abs_sobely",abs_sobely) 
cv2.imshow("both xy",abs_sobelxy) 

cv2.waitKey()
cv2.destroyAllWindows()

run:
insert image description here

2. Scharr operator:

The usage is basically the same as Sobel, the only difference is that the convolution kernel is different, and Scharr has more details and higher precision. In addition, the Scharr operator xy cannot be 1 at the same time, otherwise an exception will be reported.
insert image description here

The following example compares the Sobel kernel Scharr operator:

import cv2

o = cv2.imread('lena.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   # 转回uint8  
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 

cv2.imshow("original",o)
cv2.imshow("sobelxy",sobelxy)
cv2.imshow("scharrxy",scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()

run:
insert image description here

3. Laplacian operator:

Similar to the second-order Sobel derivative, the gradient values ​​​​need to be calculated in two directions. Calculation method: P5 = (P2+P4+P6+P8) - 4 * P5, also need to take the absolute value.
insert image description here
Example of comparison of three operators:

import cv2
o = cv2.imread('lena.bmp',cv2.IMREAD_GRAYSCALE)

# Sobel
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 

# Scharr
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   # 转回uint8  
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 

# Laplacion
lap = cv2.Laplacian(o,cv2.CV_64F)
lapxy = cv2.convertScaleAbs(lap)   # 转回uint8 

cv2.imshow("original",o)
cv2.imshow("sobelxy",sobelxy)
cv2.imshow("scharrxy",scharrxy)
cv2.imshow("lapxy",lapxy)

cv2.waitKey()
cv2.destroyAllWindows()

run:
insert image description here

4. Summary:

Both Sobel and Scharr operators are divided into xy directions, and the weighted value of Scharr is higher than that of Sobel, so the pixel values ​​in adjacent areas have a greater impact on it. But at the same time, the details are richer and the precision is high.
The Laplacian operator does not distinguish between xy and is sensitive to noise and edges.

OVER…

Guess you like

Origin blog.csdn.net/qq_34699535/article/details/119141404