canny边缘检测

实现代码:

import cv2
import numpy as np

img = cv2.imread('./tu2.jpg', 0)
print(img.shape)
height, width = img.shape

# 高斯滤波
fil = np.array([[ 1, 2, 1],
                [ 2, 4, 2],
                [ 1, 2, 1]])
fil = fil/16
res = cv2.filter2D(img,-1,fil)

# 梯度
dx = np.zeros((height, width))
dy = np.zeros((height, width))
d = np.zeros((height, width))
for i in range(1, height-1):
    for j in range(1, width-1):
        dx[i, j] = int(res[i, j+1]) - int(res[i, j])
        dy[i, j] = int(res[i+1, j]) - int(res[i, j])
        d[i, j] = np.sqrt(dx[i, j]**2 + dy[i, j]**2)
cv2.imshow('d', d)

# 非极大值抑制
k = d
for i in range(1, height-1):
    for j in range(1, width-1):
        gradX = dx[i,j]
        gradY = dy[i,j]
        gradTemp = d[i,j]
        if abs(gradY) > abs(gradX):
            weight = abs(gradX)/abs(gradY) if abs(gradY)!=0 else 1
            grad2 = d[i - 1,j]
            grad4 = d[i + 1,j]
            if gradX * gradY > 0:
                grad1 = d[i - 1,j - 1]
                grad3 = d[i + 1,j + 1]
            else:
                grad1 = d[i - 1,j + 1]
                grad3 = d[i + 1,j - 1]
        else:
            weight = abs(gradY) / abs(gradX) if abs(gradY)!=0 else 1
            grad2 = d[i,j - 1]
            grad4 = d[i,j + 1]
            if gradX * gradY > 0:
                grad1 = d[i + 1,j + 1]
                grad3 = d[i - 1,j - 1]
            else:
                grad1 = d[i - 1,j + 1]
                grad3 = d[i + 1,j - 1]
        # 利用grad1-grad4对梯度进行插值
        gradTemp1 = weight * grad1 + (1 - weight) * grad2
        gradTemp2 = weight * grad3 + (1 - weight) * grad4
        # 当前像素的梯度是局部的最大值,可能是边缘点
        if gradTemp >= gradTemp1 and gradTemp >= gradTemp2:
            k[i,j] = gradTemp
        else:
            k[i,j] = 0
cv2.imshow('k', k)

# 定义双阈值
EP_MIN = 12
EP_MAX = EP_MIN * 2
EdgeLarge = np.zeros((height, width))    #记录真边缘
EdgeBetween = np.zeros((height, width))  #记录可能的边缘点
for i in range(1, height-1):
    for j in range(1, width-1):
        if k[i,j] >= EP_MAX:
            EdgeLarge[i,j] = k[i,j]
        elif k[i,j] >= EP_MIN:
            EdgeBetween[i,j] = k[i,j]
cv2.imshow('EdgeLarge', EdgeLarge)
cv2.imshow('EdgeBetween', EdgeBetween)

# 把EdgeLarge的边缘连成连续的轮廓
edge = np.zeros((height, width))
for i in range(1, height-1):
    for j in range(1, width-1):
        if EdgeLarge[i,j] > 0:
            edge[i,j] = EdgeLarge[i,j]
            list_position = [[i-1, j-1], [i, j-1], [i+1, j-1], [i+1, j], 
                             [i+1, j+1], [i, j+1], [i-1, j+1], [i-1, j]]
            for lis in list_position:
                x = lis[0]
                y = lis[1]
                if EdgeBetween[x, y] > 0:
                    edge[x, y] = EdgeBetween[x, y]
                    EdgeBetween[x, y] = 0#避免重复计算
cv2.imshow('edge', edge)
cv2.waitKey()
cv2.destroyAllWindows()

实现结果图片:

      

      

posted @ 2019-07-10 20:50  车路历程  阅读(299)  评论(0编辑  收藏  举报