1.梯度强度计算与梯度方向计算
计算每个点的梯度强度与梯度方向
sobel_x = np.array([[1, 0, -1], [1, 0, -1], [1, 0, -1]])
sobel_y = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
grad_x = signal.convolve2d(b, sobel_x, 'same')
grad_y = signal.convolve2d(b, sobel_y, 'same')
ans = grad_x**2 + grad_y**2
# 梯度强度矩阵
ans = ans**0.5
# np.set_printoptions(1)
degree = grad_y / grad_x
# 梯度方向矩阵
degree = np.arctan(degree)
2.梯度方向离散化
将梯度方向离散化为四个方向
# 梯度方向矩阵离散化
for i in range(row):
for j in range(col):
if degree[i, j] < 0:
degree[i, j] += np.pi
if degree[i, j] > 7 * np.pi / 8:
degree[i, j] = np.pi - degree[i, j]
if (np.pi / 8 > degree[i, j] >= -np.pi / 8):
degree[i, j] = 0
elif (3 * np.pi / 8 > degree[i, j] >= np.pi / 8):
degree[i, j] = np.pi / 4
elif (5 * np.pi / 8 > degree[i, j] >= 3 * np.pi / 8):
degree[i, j] = np.pi / 2
elif (7 * np.pi / 8 > degree[i, j] >= 5 * np.pi / 8):
degree[i, j] = 3 * np.pi / 4
3.极大值抑制
将梯度方向上不是最大值的点舍弃
# 极大值抑制
yizhi = np.zeros((row, col))
for i in range(row):
for j in range(col):
if not np.isnan(degree[i, j]):
if degree[i, j] == 0:
if ans[i, j] > ans[i, max(0, j - 1)] and ans[i, j] > ans[
i, min(8, j + 1)]:
yizhi[i][j] = 1
if degree[i, j] == np.pi / 4:
if ans[i, j] > ans[max(0, i - 1),
min(8, j +
1)] and ans[i, j] > ans[min(8, i + 1),
max(0, j - 1)]:
yizhi[i][j] = 1
if degree[i, j] == np.pi / 2:
if ans[i, j] > ans[max(0, i - 1),
j] and ans[i, j] > ans[min(8, i + 1), j]:
yizhi[i][j] = 1
if degree[i, j] == 3 * np.pi / 4:
if ans[i, j] > ans[max(0, i - 1),
max(0, j -
1)] and ans[i, j] > ans[min(8, i + 1),
min(8, j + 1)]:
yizhi[i][j] = 1
4. 边缘连接
设置两个阈值,大于大的阈值可以直接被视为边缘点,介于两个阈值之间的边缘点需要看有没有绝对边缘点与其邻接,如果有可以视为边缘点,否则不视为边缘点。
# step4. 双阈值算法检测、连接边缘
W3, H3 = yizhi.shape
DT = np.zeros([W3, H3])
# 定义高低阈值
TL = 0.2 * np.max(yizhi)
TH = 0.3 * np.max(yizhi)
for i in range(1, W3-1):
for j in range(1, H3-1):
if (yizhi[i, j] < TL):
DT[i, j] = 0
elif (yizhi[i, j] > TH):
DT[i, j] = 1
elif ((yizhi[i-1, j-1:j+1] < TH).any() or (yizhi[i+1, j-1:j+1]).any()
or (yizhi[i, [j-1, j+1]] < TH).any()):
DT[i, j] = 1
源代码:
TODO: arctan等于Nan的情况好像没有处理
# -*- coding:utf-8 -*-
from scipy import signal
import numpy as np
from PIL import Image
import os
def file_name(file_dir):
L = []
N = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.jpg':
L.append(os.path.join(root, file))
N.append(file)
return L, N
np.set_printoptions(1)
sobel_y = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
name, filename = file_name('D:/Canny-publish/Images')
print(filename)
# 阈值
yuzhi = 5
b = Image.open(f'{name[1]}')
b = b.convert('L')
b = np.array(b)
sobel_x = np.array([[1, 0, -1], [1, 0, -1], [1, 0, -1]])
grad_x = signal.convolve2d(b, sobel_x, 'same')
grad_y = signal.convolve2d(b, sobel_y, 'same')
ans = grad_x**2 + grad_y**2
# 梯度强度矩阵
ans = ans**0.5
# np.set_printoptions(1)
degree = grad_y / grad_x
# 梯度方向矩阵
degree = np.arctan(degree)
row, col = b.shape
# 梯度方向矩阵离散化
for i in range(row):
for j in range(col):
if degree[i, j] < 0:
degree[i, j] += np.pi
if degree[i, j] > 7 * np.pi / 8:
degree[i, j] = np.pi - degree[i, j]
if (np.pi / 8 > degree[i, j] >= -np.pi / 8):
degree[i, j] = 0
elif (3 * np.pi / 8 > degree[i, j] >= np.pi / 8):
degree[i, j] = np.pi / 4
elif (5 * np.pi / 8 > degree[i, j] >= 3 * np.pi / 8):
degree[i, j] = np.pi / 2
elif (7 * np.pi / 8 > degree[i, j] >= 5 * np.pi / 8):
degree[i, j] = 3 * np.pi / 4
# 极大值抑制
yizhi = np.zeros((row, col))
for i in range(row):
for j in range(col):
if not np.isnan(degree[i, j]) and ans[i, j] > yuzhi:
if degree[i, j] == 0:
if ans[i, j] > ans[i, max(0, j - 1)] and ans[i, j] > ans[
i, min(8, j + 1)]:
yizhi[i][j] = 1
if degree[i, j] == np.pi / 4:
if ans[i, j] > ans[max(0, i - 1),
min(8, j +
1)] and ans[i, j] > ans[min(8, i + 1),
max(0, j - 1)]:
yizhi[i][j] = 1
if degree[i, j] == np.pi / 2:
if ans[i, j] > ans[max(0, i - 1),
j] and ans[i, j] > ans[min(8, i + 1), j]:
yizhi[i][j] = 1
if degree[i, j] == 3 * np.pi / 4:
if ans[i, j] > ans[max(0, i - 1),
max(0, j -
1)] and ans[i, j] > ans[min(8, i + 1),
min(8, j + 1)]:
yizhi[i][j] = 1
yizhi = yizhi * ans
print(yizhi)
W3, H3 = yizhi.shape
DT = np.zeros([W3, H3])
# 定义高低阈值
TL = 0.2 * np.max(yizhi)
TH = 0.3 * np.max(yizhi)
for i in range(1, W3-1):
for j in range(1, H3-1):
if (yizhi[i, j] < TL):
DT[i, j] = 0
elif (yizhi[i, j] > TH):
DT[i, j] = 255
elif ((yizhi[i-1, j-1:j+1] > TH).any() or (yizhi[i+1, j-1:j+1] > TH).any()
or (yizhi[i, [j-1, j+1]] > TH).any()):
DT[i, j] = 255
print(DT)
DT = Image.fromarray(DT)
DT.convert('1')
DT.show()