1. 直接调用 OpenCV函数

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

## 重点
img = cv.imread('pic/notebook500x333.jpg', 0)
img_edge = cv.Canny(img, 20, 200)
plt.imshow(img_edge, cmap='gray')
plt.show()

2. 效果

从左到右依次为原图、OpenCV直接调用、自己实现效果。

3. 自己实现

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

def show(img):
    if img.ndim == 2:
        plt.imshow(img, cmap='gray')
    else:
        img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
        plt.imshow(img)
    plt.show()


img = cv.imread('pic/notebook500x333.jpg', 0)

# 1. 平滑
img_blur = cv.GaussianBlur(img, (5,5), 2)

# 2. 计算梯度
gradx = cv.Sobel(img_blur, cv.CV_64F, 1, 0)
grady = cv.Sobel(img_blur, cv.CV_64F, 0, 1)
R = np.abs(gradx) + np.abs(grady)
T = np.arctan(grady / (gradx + 1e-3))

# 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):
        theta = T[i,j]
        if -np.pi / 8 <= theta < np.pi / 8:
            if R[i,j] == max([R[i,j], R[i,j-1], R[i, j+1]]):
                img_thin[i,j] = R[i,j]
        elif -3 * np.pi / 8 <= theta < -np.pi / 8:
            if R[i,j] == 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 <= theta < 3 * np.pi / 8:
            if R[i,j] == 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] == max([R[i,j], R[i-1,j], R[i+1,j]]):
                img_thin[i,j] = R[i,j]
                
# 双阈值抑制

th1 = 5
th2 = 30
maxv = 255

img_edge = np.zeros_like(img_thin)

h, w = img_thin.shape
for i in range(1, h - 1):
    for j in range(1, w - 1):
        if img_thin[i,j] >= th2:
            img_edge[i,j] = maxv
        elif img_thin[i,j] > th1:
            around = img_thin[i-1:i+2, j-1:j+2]
            if around.max() >= th2:
                img_edge[i,j] = maxv
        
show(img_edge)

说明:

  1. 未经许可,谢绝转载。
  2. 本教程为《数字图像处理Python OpenCV实战》的配套代码相关内容。
    免费视频教程为0-6章(标题号≤6),可在此处点击观看。
    所有课件及源代码可在此处下载:
    链接:https://pan.baidu.com/s/198PySe_vebO3e06idHSQ6g
    提取码:11o4
    有问题可在QQ群(1079300899)指出,进群答案:数字图像处理。在本文评论指出可能导致回复很晚。