import cv2
import numpy as np
import math
def canny(img,threshold1,threshold2):
#1.用高斯滤波器进行模糊处理去除噪声,使用的是二维高斯函数
#先转为灰度图
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#高斯滤波器
gauss=cv2.GaussianBlur(gray,(5,5),1) #高斯核的size为5*5,标准差为1
#转化为可视化的图像标准
gauss_new=np.uint8(np.copy(gauss))
cv2.imshow('GuassianBlur',gauss_new)
#2.算梯度值以及方向(使用Sobel算子实现)
w1,h1=gauss.shape
## print(h1,w1)
#用于Sobel x轴方向的核
dx=np.zeros([w1-1,h1-1]) ##保留疑问为什么要减一
#用于Sobel y轴方向的核
dy=np.zeros([w1-1,h1-1])
#储存梯度值的数组
d=np.zeros([w1-1,h1-1])
#储存方向的数组
ddegree=np.zeros([w1-1,h1-1])
## x轴方向的核
## 1 0 -1
## 2 0 -2
## 1 0 -1
## y轴方向的核
## 1 2 1
## 0 0 0
## -1 -2 -1
for i in range(1,w1-1): #因为从1开始的,这样下面操作不会越界,结尾也所以用h1-1
for j in range(1,h1-1):
dx[i,j]=gauss[i-1,j-1]+2*gauss[i,j-1]+gauss[i+1,j-1]-gauss[i-1,j+1]-2*gauss[i,j+1]-gauss[i+1,j+1]
dy[i,j]=gauss[i-1,j-1]+2*gauss[i-1,j]+gauss[i-1,j+1]-gauss[i+1,j-1]-gauss[i+1,j]-gauss[j+1,j+1]
#算梯度值,且作为图像强度值
d[i,j]=np.sqrt(np.square(dx[i,j])+np.square(dy[i,j]))
#算对应梯度方向
ddegree[i,j]=math.degrees(math.atan2(dy[i,j],dx[i,j]))
if ddegree[i,j]<0:
ddegree[i,j]+=360
tidu=np.uint8(np.copy(d))
cv2.imshow('tidu',tidu)
#3.非极大值抑制
w2,h2=d.shape
nms=np.copy(d)
nms[0,:]=nms[w2-1,:]=nms[:,0]=nms[:,h2-1]=0
g1=0
g2=0
for i in range(1,w2-1):
for j in range(1,h2-1):
if d[i,j]==0:
nms[i,j]=0
else:
g1=None
g2=None
if (ddegree[i,j]>=0 and ddegree[i,j]<=22.5) or (ddegree[i,j]>=337.5):
g1=nms[i,j-1]
g2=nms[i,j+1]
elif (ddegree[i,j]<=67.5 and ddegree[i,j]>22.5) or(ddegree[i,j]>=202.5 and ddegree[i,j]<=247.5):
g1=nms[i+1,j+1]
g2=nms[i-1,j-1]
elif (ddegree[i,j]>67.5 and ddegree[i,j]<=112.5) or(ddegree[i,j]>247.5 and ddegree[i,j]<=292.5):
g1=nms[i+1,j]
g2=nms[i-1,j]
elif (ddegree[i,j]>112.5 and ddegree[i,j]<=157.5) or (ddegree[i,j]>292.5 and ddegree[i,j]<337.5):
g1=nms[i-1,j-1]
g2=nms[i+1,j+1]
else:
g1=nms[i,j-1]
g2=nms[i,j+1]
if nms[i,j]<g1 or nms[i,j]<g2:
nms[i,j]=0
fjida=np.uint8(np.copy(nms))
cv2.imshow('fjida',fjida)
#双阈值算法检测及连接边缘
w3,h3=nms.shape
Dt=np.zeros([w3,h3],dtype=np.uint8)
Tl=min(threshold1,threshold2)
Th=max(threshold1,threshold2)
for i in range(1,w3-1):
for j in range(1,h3-1):
if nms[i,j]<Tl:
Dt[i,j]=0
elif nms[i,j]>Th:
Dt[i,j]=255
else:
if nms[i-1,j] > Th or nms[i-1,j-1] > Th or nms[i-1,j+1]>Th or nms[i,j-1]>Th\
or nms[i,j+1]>Th or nms[i+1,j] >Th or nms[i+1,j-1] >Th or nms[i+1,j+1] > Th:
Dt[i,j]=255
return Dt
if __name__=='__main__':
img=cv2.imread('cat1.jpg')
result=canny(img,60,120)
cv2.imshow('finnal',result)
Canny边缘检测算法学习笔记
最新推荐文章于 2023-08-07 13:42:07 发布