数字图像处理_图像边缘提取

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()

Prewitt、Roberts算子

cv.filter2D(img, -1, kernel)

Prewitt算子

在这里插入图片描述
在这里插入图片描述

# Prewitt算子
img = cv.imread('pic/gift500x500.jpg', 0)

kx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=np.float32)
ky = np.array([[-1,0, 1], [-1,0, 1], [-1,  0,  1]], dtype=np.float32)

imgx = cv.filter2D(img, cv.CV_16S, kx)
imgy = cv.filter2D(img, cv.CV_16S, ky)

absX = cv.convertScaleAbs(imgx)
absY = cv.convertScaleAbs(imgy)

img_prewitt = cv.add(absX, absY) # np.uint8
show(img_prewitt)

在这里插入图片描述

cv.imwrite('pic/gift_premitt_xy.jpg', np.hstack([img, absX, absY, img_prewitt]))

True

# 锐化
img_pre_sharp1 = cv.addWeighted(img, 0.9, img_prewitt, 0.2, 0)
img_pre_sharp2 = cv.add(img, img_prewitt)
show(np.hstack([img, img_pre_sharp1, img_pre_sharp2]))

在这里插入图片描述

Roberts算子

在这里插入图片描述

在这里插入图片描述

# Roberts算子
img = cv.imread('pic/gift500x500.jpg', 0)

kx = np.array([[-1, 0], [0, 1]], dtype=np.float32)
ky = np.array([[0, -1], [1, 0]], dtype=np.float32)

imgx = np.abs(cv.filter2D(img, cv.CV_16S, kx))
imgy = np.abs(cv.filter2D(img, cv.CV_16S, ky))

img_robert = cv.convertScaleAbs(np.abs(imgx) + np.abs(imgy)) # np.uint8

show(np.hstack([img, img_robert])) 

在这里插入图片描述

cv.imwrite('pic/gift_premitt_roberts.jpg', np.hstack([img, img_prewitt, img_robert]))

True

Sobel算子

cv.Sobel(img, cv.CV_16S, 1, 0, ksize=3)

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述

grad_x = cv.Sobel(img, cv.CV_16S, 1, 0, ksize=3)
grad_y = cv.Sobel(img, cv.CV_16S, 0, 1, ksize=3)

grad_xabs = np.abs(grad_x)
grad_yabs = np.abs(grad_y)
grad_xy   = grad_xabs + grad_yabs

show(np.hstack([img, grad_xabs, grad_yabs, grad_xy]))

在这里插入图片描述

Scharr算子

cv.Scharr(img, cv.CV_64F, 0, 1, ksize=3)
img = cv.imread('pic/bookshelf500x333.jpg', 0)

grad_x = np.abs(cv.Scharr(img, -1, 1, 0))
grad_y = np.abs(cv.Scharr(img, -1, 0, 1))
img_grad = cv.add(grad_x, abs(grad_y))

show(np.hstack([img, img_grad]))
show(np.hstack([grad_x, grad_y]))

在这里插入图片描述
在这里插入图片描述

Laplacian算子

cv.Laplacian(img, cv.CV_16S)

在这里插入图片描述

在这里插入图片描述

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

img_lap = cv.Laplacian(img, cv.CV_16S, ksize=5, scale=0.2)

img_lap2 = np.abs(img_lap).clip(0, 255)
show(np.hstack([img, img_lap2]))

在这里插入图片描述

LOG算子

在这里插入图片描述

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

img_g = cv.GaussianBlur(img, (3,3), 0)
img_log = cv.Laplacian(img_g, cv.CV_16S, ksize=5, scale=0.2)

img_log2 = np.abs(img_log).clip(0, 255)
show(np.hstack([img, img_log2]))

在这里插入图片描述

cv.imwrite('pic/notebook_lap_log.jpg', np.hstack([img, img_lap2, img_log2]))

True

边缘检测——Canny算法

cv.Canny(img, 20, 200)

在这里插入图片描述

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

img_canny = cv.Canny(img, 20, 200)

show(np.hstack([img, img_canny]))

在这里插入图片描述

cv.imwrite('test/landmark_canny.jpg', np.hstack([img, img_canny]))

True

Canny 边缘检测实现

  1. 平滑:模糊削弱噪声。
  2. 计算梯度:梯度包括大小和方向,由x和y方向合成。
  3. 细化边缘:利用非极大值抑制,只有局部最大值保留为边缘。
  4. 双阈值抑制:根据大小两个阈值,高于大阈值的为确定的边缘(强边缘);低于小阈值的不是边缘;处于两者之间的像素点(弱边缘)下一步确定。
  5. 边缘追踪:对于弱边缘,如果和强边缘相连,则也为边缘,否则不是边缘
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
img = cv.imread('pic/notebook500x333.jpg', 0)

# Gaussian 滤波
img_blur = cv.GaussianBlur(img, (5, 5), 2)
# 梯度
gradx = cv.Sobel(img_blur, cv.CV_64F, 1, 0)
grady = cv.Sobel(img_blur, cv.CV_64F, 0, 1)

T = np.arctan(grady /(gradx + 1e-3))
R = np.abs(gradx) + np.abs(grady)
show(np.hstack([np.abs(gradx).clip(0,255), np.abs(grady).clip(0,255), R.clip(0,255)]))

在这里插入图片描述

h, w = R.shape

img_thin = np.zeros_like(R, dtype=np.float64)

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]
                
show(np.abs(img_thin).clip(0,255))

在这里插入图片描述

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)

在这里插入图片描述

R2 = np.abs(R).clip(0,255)
img_thin2 = np.abs(img_thin).clip(0, 255)

show(np.hstack([img_blur, R2, img_thin2, img_edge]))

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

¥骁勇善战¥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值