Pyhton实现边缘检测Robert算子、Sobel算子、Canny算子
程序员文章站
2024-01-28 08:54:58
...
这次我们学习一下计算机视觉的边缘检测算子,主要介绍Robert、Sobel、Canny算子的python实现。
1、Canny算法,主要有以下步骤:
(1)灰度化(通常灰度化采用的公式是:Gray=0.299R+0.587G+0.114B;)
(2)高斯滤波
(3)计算图像的梯度和梯度方向,(本文使用Sobel算子)
(4)非极大值抑制(上一步得到的边缘较粗,这里会细化边缘)
(5)双阈值筛选边缘(二值化显示)
// Canny算子实现
import numpy as np
import cv2
import math
def Canny(img,threshold1,threshold2):
#step1:高斯滤波
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
new_gray=cv2.GaussianBlur(gray,(5,5),1)
#展示高斯滤波后的图片
# gaus_result=new_gray.copy()
gaus_result=np.uint8(np.copy(new_gray))
cv2.imshow('gaus',gaus_result)
# cv2.waitKey(0)
#step2:求梯度值及梯度方向
W1,H1=new_gray.shape
print(new_gray.shape)
dx=np.zeros([W1-1,H1-1])
dy=np.zeros([W1-1,H1-1])
#求出的图像值
d=np.zeros([W1-1,H1-1])
#梯度方向
dgree=np.zeros([W1-1,H1-1])
for i in range(1,W1-1):
for j in range(1,H1-1):
#dx水平方向
dx[i,j]=new_gray[i-1,j-1]+2*new_gray[i,j-1]+new_gray[i+1,j-1]-\
new_gray[i-1,j+1]-2*new_gray[i,j+1]-new_gray[i+1,j+1]
#dy垂直方向
dy[i,j]=new_gray[i-1,j-1]+2*new_gray[i-1,j]+new_gray[i-1,j+1]-\
new_gray[i+1,j-1]-2*new_gray[i+1,j]-new_gray[i+1,j+1]
#G=sqrt(Gx**2+Gy**2)
d[i,j]=np.sqrt(np.square(dx[i,j])+np.square(dy[i,j]))
#math.atan2求出弧度,math.degrees转为角度
dgree[i,j]=math.degrees(math.atan2(dy[i,j],dx[i,j]))
if dgree[i,j]<0:
dgree+=360
#
d_show=np.uint8(np.copy(d))
cv2.imshow('d_show',d_show)
#非极大值抑制
W2, H2=d.shape
NMS=np.uint8(np.copy(d))
NMS[0,:]=NMS[W2-1,:]=NMS[:,0]=NMS[:,H2-1]=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
#也可以使用插值方法,此处为设定角度计算
#0度水平方向
if (dgree[i,j]<=22.5 and dgree[i,j]>=0) or (dgree[i,j]>=337.5):
g1=NMS[i,j-1]
g2=NMS[i,j+1]
#45度方向
elif (dgree[i,j]<=67.5 and dgree[i,j]>22.5) or (dgree[i,j]<=337.5 and dgree[i,j]>292.5):
g1=NMS[i-1,j+1]
g2=NMS[i+1,j-1]
#90度方向
elif (dgree[i,j]<=112.5 and dgree[i,j]>67.5) or (dgree[i,j]<=292.5 and dgree[i,j]>247.5):
g1=NMS[i-1,j]
g2=NMS[i+1,j]
#135度方向
elif (dgree[i,j]<=157.5 and dgree[i,j]>112.5) or (dgree[i,j]<=247.5 and dgree[i,j]>202.5):
g1=NMS[i-1,j-1]
g2=NMS[i+1,j+1]
#180度方向
else:
g1=NMS[i,j-1]
g2=NMS[i,j+1]
#如果当前值小于梯度方向上的任一值,则NMS[i,j]=0,否则保留原值
if NMS[i,j]<g1 or NMS[i,j]<g2:
NMS[i,j]=0
cv2.imshow('NMS_show',NMS)
#双阈值算法检测,连接边缘
W3,H3=NMS.shape
DT=np.zeros([W3,H3])
#定义高低阈值
TL=min(threshold1,threshold2)
TH=max(threshold1,threshold2)
for i in range(1,W3-1):
for j in range(1,H3-1):
#小于TL的值设置为0
if (NMS[i,j]<TL):
DT[i,j]=0
#大于TH的值设置为255,即边缘
elif (NMS[i,j]>TH):
DT[i,j]=255
#对于在TL~TH之间的数,如果相邻点大于TH,即和边缘值有连接,则也为边缘值,设置为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
img=cv2.imread('data/lena.png')
cv2.imshow('orginal_img',img)
canny_img=Canny(img,50,140)
cv2.imshow('canny_img',canny_img)
cv2.waitKey(0)
#OpenCV实现Canny算子
# import cv2
#
# img=cv2.imread('data/lena.png')
# canny_img=cv2.Canny(img,150,200)
# cv2.imshow('canny_img',canny_img)
# cv2.waitKey(0)
原图
step1:高斯滤波
step2:sobel算子得到边缘
step3:非极大值抑制(上一步得到的边缘较粗,这里会细化边缘)
step4:双阈值筛选边缘(二值化显示),输出Canny结果。
2、Robert算子
原理可以参考文章:https://blog.csdn.net/u013007900/article/details/78301951
代码实现入下。
// Robert算子
import cv2
#robert算子[[-1,-1],[1,]]
def robert(img):
w,h=img.shape[:2]
r=[[-1,-1],[1,1]]
for i in range(w):
for j in range(h):
if (j+2<h) and (i+2<=w):
process_img=img[i:i+2,j:j+2]
list_robert=r*process_img
img[i,j]=abs(list_robert.sum())
return img
img=cv2.imread('data/lena.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('orl_img',img)
img=robert(img)
cv2.imshow('robert',img)
cv2.waitKey(0)
原图
Robert结果
3、Sobel算子
原理参考:边缘检测:Canny算子,Sobel算子
代码实现
// Sobel算子
import cv2
import numpy as np
def sobel(img):
w,h=img.shape
new_img=np.zeros([w,h])
x_img=np.zeros(img.shape)
y_img=np.zeros(img.shape)
sobel_x=np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
sobel_y=np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
for i in range(w-2):
for j in range(h-2):
x_img[i+1,j+1]=abs(np.sum(img[i:i+3,j:j+3]*sobel_x))
y_img[i+1,j+1]=abs(np.sum(img[i:i+3,j:j+3]*sobel_y))
new_img[i+1,j+1]=np.sqrt(np.square(x_img[i+1,j+1])+np.square(y_img[i+1,j+1]))
return np.uint8(new_img)
img=cv2.imread('data/lena.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('orl_img',img)
img=sobel(img)
cv2.imshow('sobel',img)
cv2.waitKey(0)
原图灰度后
Sobel算子结果
上一篇: 图像处理25:边缘检测
推荐阅读
-
opencv——图像边缘检测(上)sobel算子
-
【opencv学习笔记】020之边缘检测与Canny算子
-
边缘检测 - Sobel算子
-
Pyhton实现边缘检测Robert算子、Sobel算子、Canny算子
-
边缘检测 sobel算子
-
【图像处理】Sobel算子实现水平边缘检测、垂直边缘检测;45度、135度角边缘检测
-
OpenCV图像处理教程C++(十五)边缘检测算法--sobel算子、拉普拉斯算子、Canny算子
-
【OpenCV】边缘检测:Sobel、拉普拉斯算子
-
python—opencv图像膨胀|图像腐蚀|图像边缘检测sobel算子/拉普拉斯算子/canny算子
-
Java实现Canny算子边缘提取