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