Canny边缘检测-python

在这里插入图片描述

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

volcanical

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值