Canny边缘检测算法学习笔记

 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)

参考:https://www.bilibili.com/video/BV1U4411277i

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值