索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是以离散性差分算子,用来计算凸显两素函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是法矢量。
Sobel 的卷积因子为:
该算子包含两组3 * 3 的矩阵,分别为横向和纵向,将之与图像做平面卷积,即可分别得出横向及纵向的亮度差
分近似值,若以A代表为原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
G x = [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] × A a n d G y = [ + 1 + 2 + 1 0 0 0 − 1 − 2 − 1 ] × A G_x=\left[ \begin{matrix} -1& 0& +1\\ -2& 0& +2\\ -1& 0& +1\\ \end{matrix} \right] \times A\ and\ G_y=\left[ \begin{matrix} +1& +2& +1\\ 0& 0& 0\\ -1& -2& -1\\ \end{matrix} \right] \times A\ Gx=⎣⎡−1−2−1000+1+2+1⎦⎤×A and Gy=⎣⎡+10−1+20−2+10−1⎦⎤×A
图像的每一像素的横向以及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
G = G x 2 + G y 2 G=\sqrt{G_x^2+G_y^2}\ G=Gx2+Gy2
通常,为了提高计算的效率,也使用以下公式计算:
∣ G ∣ = ∣ G x ∣ + ∣ G y ∣ \left| G \right|=\left| G_x \right|+\left| G_y \right| ∣G∣=∣Gx∣+∣Gy∣
import cv2 as cv
import math
import numpy as np
def rgb2gray(img):
h=img.shape[0]
w=img.shape[1]
img1=np.zeros((h,w),np.uint8)
for i in range(h):
for j in range(w):
img1[i, j] = np.max(img[i, j])
return img1
def otsu(img):
h=img.shape[0]
w=img.shape[1]
m=h*w
otsuimg=np.zeros((h,w),np.uint8)
threshold_max=threshold=0
histogram=np.zeros(256,np.int32)
probability=np.zeros(256,np.float32)
for i in range (h):
for j in range (w):
s=img[i,j]
histogram[s]+=1
for k in range (256):
probability[k]=histogram[k]/m
for i in range (255):
w0 = w1 = 0
fgs = bgs = 0
for j in range (256):
if j<=i:
w0+=probability[j]
fgs+=j*probability[j]
else:
w1+=probability[j]
bgs+=j*probability[j]
u0=fgs/w0
u1=bgs/w1
g=w0*w1*(u0-u1)**2 # 类间方差
if g>=threshold_max:
threshold_max=g
threshold=i
print(threshold)
for i in range (h):
for j in range (w):
if img[i,j]>threshold:
otsuimg[i,j]=255
else:
otsuimg[i,j]=0
return otsuimg
def sobel(img):
h=img.shape[0]
w=img.shape[1]
sobelimg=np.zeros((h,w),np.uint8)
sobelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
sobelx=np.array(sobelx)
sobely=np.array(sobely)
for i in range(1,h-1):
for j in range(1,w-1):
edgex=0
edgey=0
for k in range(-1,2):
for l in range(-1,2):
edgex+=img[k+i,l+j]*sobelx[1+k,1+l]
edgey+=img[k+i,l+j]*sobely[1+k,1+l]
gx=abs(edgex)
gy=abs(edgey)
gramag=gx+gy
sobelimg[i,j]=gramag
return sobelimg
image= cv.imread(r"pin1.jpg")
grayimage=rgb2gray(image)
otsuimage=otsu(grayimage)
cv.imshow("grayimage",otsuimage)
sobelimage=sobel(otsuimage)
cv.imshow("image",image)
cv.imshow("sobelimage",sobelimage)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread(r"3.jpg")
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
absX = cv2.convertScaleAbs(x) # 转回unit8
absY = cv2.convertScaleAbs(y)
dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
cv2.imshow("absX", absX)
cv2.imshow("absY", absY)
cv2.imshow("Result", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()