NumPy实现Canny算法

步骤

1.平滑:模糊削弱噪声。

2. 计算梯度,用Sobel算子计算像素的梯度,计算得到垂直梯度和水平梯度,即为Gx和Gy, 像素的总梯度是

3. 细化边缘:用非极大值抑制,局部最大值保留为边缘。参考坐标如下:

4. 双阈值抑制:根据大小两个阈值(由编码者给定),如果某点的像素高于大阈值的确定为边缘,保留。低于小阈值的不是边缘,置为0。小阈值<某点的像素<=大阈值,遍历这个像素相邻的8个像素,如果8个中有一个的像素>大阈值,则说明,某点的像素与强边缘相连,则保留某点的像素。

代码实现:

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

def showImage(name,img):
    plt.imshow(img,cmap="gray")
    plt.title(name)
    plt.show()

# 检测轮廓
def canny(img,th1,th2):
    #平滑
    img2=cv.GaussianBlur(img,(5,5),2)
    #计算梯度
    gradx=cv.Sobel(img,cv.CV_64F,1,0)
    grady=cv.Sobel(img,cv.CV_64F,0,1)

    # 计算每个像素的总梯度
    R=np.sqrt((gradx)**2+(grady)**2)
    # 计算梯度的方向 (gradx+1e-3)防止分母为0
    T=np.arctan(grady/(gradx+1e-3))

    #细化边缘
    (h,w)=R.shape
    img_thin=np.zeros_like(R)
    # 细化边缘按照梯度方向,非极大值抑制
    for i in range(1, h - 1):
        for j in range(1, w - 1):
            thetha = T[i, j]
            # 像素和左右的比较
            if -np.pi / 8 <= thetha < np.pi / 8:
                if R[i, j] == np.max([R[i, j], R[i][j - 1], R[i][j + 1]]):
                    img_thin[i, j] = R[i, j]
            # 像素和右上角和左下角比价
            elif -3 * np.pi / 8 <= thetha < -np.pi / 8:
                if R[i, j] == np.max([R[i, j], R[i + 1][j - 1], R[i - 1][j + 1]]):
                    img_thin[i, j] = R[i, j]
            # 像素和右下角、左上角比较
            elif np.pi / 8 <= thetha < 3 * np.pi / 8:
                if R[i, j] == np.max([R[i, j], R[i + 1][j + 1], R[i - 1][j - 1]]):
                    img_thin[i, j] = R[i, j]
            # 像素和上下比较
            else:
                if R[i, j] == np.max([R[i, j], R[i - 1][j], R[i + 1][j]]):
                    img_thin[i, j] = R[i, j]

    (h,w)=img_thin.shape
    #细化边缘,双边阈值
    edge=np.zeros_like(img_thin,dtype=np.uint8)
    for i in range(1,h-1):
        for j in range(1,w-1):
            #大于th2是强边缘,保留
            if img_thin[i,j]>=th2:
                edge[i,j]=255
            #th1<像素<=th2,周围8像素有强边缘的话,保留,没有默认0
            elif img_thin[i,j]>th1:
                around=img_thin[i-1:i+2,j-1:j+2]
                if around.max()>=th2:
                    edge[i,j]=255

    return edge;
if __name__=="__main__":
    img=cv.imread("../image/goldpig.jpg",0)
    edge1=canny(img,75,200)
    showImage("goldpig",img)
    showImage("goldpig2",edge1)

原图和轮廓图对比:

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值