数字图像处理——边缘检测Roberts算子、Prewitt算子、Sobel算子、Canny算子、Laplacian(拉普拉斯)算子、 Marr-Hildreth

边缘检测的基本方法有很多:

一阶的有Roberts Cross算子,Prewitt算子,Sobel算子,Canny算子,Krisch算子,罗盘算子;

二阶的还有Laplacian算子Marr-Hildreth。 

Roberts算子边缘检测


import cv2
import numpy as np
from scipy import signal

def roberts(I, _boundary='fill', _fillvalue=0):
    # 图像的高,宽
    H1, W1 = I.shape[0:2]

    # 卷积核的尺寸
    H2, W2 = 2, 2
    # 卷积核1 和 锚点的位置
    R1 = np.array([[1, 0], [0, -1]], np.float32)
    kr1, kc1 = 0, 0
    # 计算full卷积
    IconR1 =signal.convolve2d(I,R1,mode='full', boundary=_boundary, fillvalue=_fillvalue)
    IconR1 = IconR1[H2 - kr1 - 1:H1 + H2 - kr1 - 1, W2 - kc1 - 1:W1 + W2 - kc1 - 1]

    # 卷积核2 和 锚点的位置
    R2 = np.array([[0, 1], [-1, 0]], np.float32)
    kr2, kc2 = 0, 1
    # 再计算full卷积
    IconR2=signal.convolve2d(I,R2, mode='full', boundary=_boundary, fillvalue=_fillvalue)
    IconR2 = IconR2[H2 - kr2 - 1:H1 + H2 - kr2 - 1, W2 - kc2 - 1:W1 + W2 - kc2 - 1]

    return (IconR1, IconR2)


if __name__ == '__main__':
    I = cv2.imread('./cat/cat1_noise.jpg', cv2.IMREAD_GRAYSCALE)
    # 显示原图
    cv2.imshow('origin', I)
    # 卷积,注意边界一般扩充采用的symm
    IconR1, IconR2 = roberts(I, 'symm')

    # 45度方向上的边缘强度的灰度级显示
    IconR1 = np.abs(IconR1)
    edge45 = IconR1.astype(np.uint8)
    cv2.imshow('edge45', edge45)

    # 135度方向上的边缘强度的灰度级显示
    IconR2 = np.abs(IconR2)
    edge135 = IconR2.astype(np.uint8)
    cv2.imshow('edge135', edge135)

    # 用平方和的开方来衡量最后输出的边缘
    edge = np.sqrt(np.power(IconR1, 2.0) + np.power(IconR2, 2.0))
    edge = np.round(edge)
    edge[edge > 255] = 255
    edge = edge.astype(np.uint8)

    # 显示边缘
    cv2.imshow('edge', edge)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Prewitt算子

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread('./cat/cat1.png')
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Prewitt算子
kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=int)
kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=int)
x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx)
y = cv2.filter2D(grayImage, cv2.CV_16S, kernely)
# 转uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Prewitt = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图形
titles = ['原始图像', 'Prewitt算子']
images = [lenna_img, Prewitt]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

Sobel算子

import cv2

img = cv2.imread("./cat/cat1.png")
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# -------------------Sobel边缘检测------------------------
x = cv2.Sobel(gray_img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(gray_img, cv2.CV_16S, 0, 1)
# cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
# 可选参数alpha是伸缩系数,beta是加到结果上的一个值,结果返回uint类型的图像
Scale_absX = cv2.convertScaleAbs(x)  # convert 转换  scale 缩放
Scale_absY = cv2.convertScaleAbs(y)
result = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# ----------------------显示结果----------------------------
cv2.imshow('img', gray_img)
cv2.imshow('Scale_absX', Scale_absX)
cv2.imshow('Scale_absY', Scale_absY)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Canny算子


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

img = cv.imread('./cat/cat1.png',0)
edges = cv.Canny(img, 100, 200)

plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()

Laplacian(拉普拉斯)算子


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

# 读取图像
img = cv2.imread('./cat/cat1.png')
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 拉普拉斯算法
dst = cv2.Laplacian(grayImage, cv2.CV_16S, ksize=3)
Laplacian = cv2.convertScaleAbs(dst)
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示图形
titles = ['原始图像', 'Laplacian算子']
images = [lenna_img, Laplacian]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 Marr-Hildreth边缘检测


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

def edgesMarrHildreth(img, sigma):
    # 根据输入的高斯标准差确定窗口大小,3 * sigma占99.7%
    size = int(2 * (np.ceil(3 * sigma)) + 1)
    # 生成(-size / 2 + 1, size / 2 )的网格
    x, y = np.meshgrid(np.arange(-size / 2 + 1, size / 2 + 1), np.arange(-size / 2 + 1, size / 2 + 1))
    # 计算LoG核
    kernel = ((x ** 2 + y ** 2 - (2.0 * sigma ** 2)) / sigma ** 4) * np.exp(
        -(x ** 2 + y ** 2) / (2.0 * sigma ** 2))  # LoG filter

    kern_size = kernel.shape[0]
    # 生成与输入图像相同大小的全零矩阵log
    log = np.zeros_like(img, dtype=float)

    # 应用LoG核
    for i in range(img.shape[0] - (kern_size - 1)):
        for j in range(img.shape[1] - (kern_size - 1)):
            window = img[i:i + kern_size, j:j + kern_size] * kernel
            log[i, j] = np.sum(window)

    # 将log由float转换为int64
    log = log.astype(np.int64, copy=False)

    # 生成与log相同大小的全零矩阵zero_crossing
    zero_crossing = np.zeros_like(log)

    # 判断零交叉点
    for i in range(log.shape[0] - (kern_size - 1)):
        for j in range(log.shape[1] - (kern_size - 1)):
            if log[i][j] == 0:
                if (log[i][j - 1] < 0 and log[i][j + 1] > 0) or (log[i][j - 1] < 0 and log[i][j + 1] < 0) or (
                        log[i - 1][j] < 0 and log[i + 1][j] > 0) or (log[i - 1][j] > 0 and log[i + 1][j] < 0):
                    zero_crossing[i][j] = 255
            if log[i][j] < 0:
                if (log[i][j - 1] > 0) or (log[i][j + 1] > 0) or (log[i - 1][j] > 0) or (log[i + 1][j] > 0):
                    zero_crossing[i][j] = 255

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值