数字图像处理:(5)非微分算子在数字图像处理中的应用

news/2024/9/19 7:11:44

本节是非微分边缘检测算子——Canny算子

边缘是图像中灰度有阶跃变化,或屋顶变化的像素的结合。

 

 1、  Canny算子边缘检测基本原理

        该算子功能比前面几种都要好,但是它实现起来较为麻烦,Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,在进行处理前,Canny算子先利用高斯平滑滤波器来平滑图像以除去噪声,Canny分割算法采用一阶偏导的有限差分来计算梯度幅值和方向,在处理过程中,Canny算子还将经过一个非极大值抑制的过程,最后Canny算子还采用两个阈值来连接边缘。

2、  Canny算子算法步骤

第一步:用高斯滤波器平滑图像。

见链接:https://blog.csdn.net/m0_37957160/article/details/119377528

第二步:计算整个图像的每一个像素的梯度幅值和梯度方向。

 数字图像处理中提供了好多种算子,计算图像的梯度和梯度方向。比如Sobel算子。

比如下边是使用Sobel算子计算的整个图像中每一个像素的梯度和方向:

现在边太粗了需要变细。

第三步:对梯度幅值进行非极大值抑制。

Canny算法论文里边是这样介绍的:在上述梯度矩阵(包含大小和方向 ),这个梯度方向有可能不是离散的,是连续的。那么论文里边假设我就关注如下的4个轴即4个方向 ,

假设只关注4个方向,

 比如说某一个梯度的方向是30度,那么在0到45度之间他是离45度方向比较近,那么就规定他为45度。就是查看他在上述方向划分的模式下,离哪一个比较近就把他的方向归并到哪一个方向上。

因为图像的像素分布是离散的,如果把其中一个像素的8邻域按照上述模式盖上去,

 

上述的NMS是Canny论文里边的思路,有后人改进的思想:用亚像素去线性差值的方法去进行非极大值抑制。

第四步:用双阈值算法检测和连接边缘。(阈值A和阈值B)

(PS:如果只是单一阈值的话,你这个阈值调的比较高,那整个图像里边一些细微的边缘(即非极大值抑制之后他那些梯度比较小的边)很可能就直接被扔掉了,但是呢,如果把阈值设置的比较低,好多杂乱无章的边也会包含进来,所以引进了双阈值)

如果做完NMS的梯度值小于阈值A的话,那么该点直接扔掉,比如说赋值为0;如果这个值比我设置的B值还要大的话,那么就认为该点是边缘点;如果在A和B之间的点叫做中庸点,对待中庸点会分两种情况:第一种情况就是该中庸点与已经确定的边缘点所组成的边有关系(就是相连,该中庸点与确定的边界相连),那么就认为该中庸点也是一个边缘点(置为255),如果该中庸点在一条边上那么该边也被认为是一条边界边。反之那么认为该中庸点是非边缘点。

3 、 Canny算子python实现

import cv2
import numpy as np
import mathdef Canny(img, threshold1, threshold2):# 高斯滤波gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)new_gray = cv2.GaussianBlur(gray, (5, 5), 1)gaussian_result = np.uint8(np.copy(new_gray))cv2.imshow('gaussian',gaussian_result)# 算梯度幅值W1, H1 = new_gray.shape[:2]dx = np.zeros([W1 - 1, H1 - 1])dy = np.zeros([W1 - 1, H1 - 1])d = np.zeros([W1 - 1, H1 - 1])ddgree = np.zeros([W1 - 1, H1 - 1])for i in range(1, W1 - 1):for j in range(1, H1 - 1):dx[i, j] = new_gray[i - 1, j - 1] + 2 * new_gray[i, j - 1] + new_gray[i + 1, j - 1] - \new_gray[i - 1, j + 1] - 2 * new_gray[i, j + 1] - new_gray[i + 1, j + 1]dy[i, j] = new_gray[i - 1, j - 1] + 2 * new_gray[i - 1, j] + new_gray[i - 1, j + 1] - \new_gray[i + 1, j - 1] - 2 * new_gray[i + 1, j] - new_gray[i + 1, j + 1]d[i, j] = np.sqrt(np.square(dx[i, j]) + np.square(dy[i, j]))  # 图像梯度幅值作为图像强度值ddgree[i, j] = math.degrees(math.atan2(dy[i, j], dx[i, j]))if ddgree[i, j] < 0:ddgree += 360d_r = np.uint8(np.copy(d))cv2.imshow('tidu', d_r)# 非极大值抑制W2, H2 = d.shapeNMS = np.copy(d)NMS[0, :] = NMS[W2 - 1, :] = NMS[:, 0] = NMS[:, H2 - 1] = 0for i in range(1, W2 - 1):for j in range(1, H2 - 1):if d[i, j] == 0:NMS[i, j] = 0else:g1 = Noneg2 = Noneif (ddgree[i, j] <= 22.5 and ddgree[i, j] >= 0) or (ddgree[i, j] >= 337.5):g1 = NMS[i, j - 1]g2 = NMS[i, j + 1]elif (ddgree[i, j] <= 67.5 and ddgree[i, j] > 22.5) or (ddgree[i, j] <= 337.5 and ddgree[i, j] > 292.5):g1 = NMS[i - 1, j + 1]g2 = NMS[i + 1, j - 1]elif ddgree[i, j] <= 112.5 and ddgree[i, j] > 67.5 or (ddgree[i, j] <= 292.5 and ddgree[i, j] > 247.5):g1 = NMS[i - 1, j]g2 = NMS[i + 1, j]elif (ddgree[i, j] <= 157.5 and ddgree[i, j] > 112.5) or (ddgree[i, j] <= 247.5 and ddgree[i, j] > 202.5):g1 = NMS[i - 1, j - 1]g2 = NMS[i + 1, j + 1]else:g1 = NMS[i, j - 1]g2 = NMS[i, j + 1]if NMS[i, j] < g1 or NMS[i, j] < g2:NMS[i, j] = 0nms_r = np.uint8(np.copy(NMS))cv2.imshow('nms', nms_r)# 双阈值算法检测、连接边缘W3, H3 = NMS.shapeDT = np.zeros([W3, H3], dtype=np.uint8)# 定义高低阈值TL = min(threshold1, threshold2)TH = max(threshold1, threshold2)for i in range(1, W3 - 1):for j in range(1, H3 - 1):if (NMS[i, j] < TL):DT[i, j] = 0elif (NMS[i, j] > TH):DT[i, j] = 255else:if NMS[i - 1, j] > TH or NMS[i - 1, j - 1] > TH or NMS[i - 1, j + 1] > TH or NMS[i, j - 1] > TH \or NMS[i, j + 1] > TH or NMS[i + 1, j] > TH or NMS[i + 1, j - 1] > TH or NMS[i + 1, j + 1] > TH: \DT[i, j] = 255return DTimg = cv2.imread('test.jpg')
cv2.imshow('src', img)
result = Canny(img, 60, 120)
cv2.imshow('dst', result)
cv2.waitKey(0)

结果如下:

 4、扩展部分

(1)边缘检测算子比较:

 (2)边缘提取和边缘跟踪:

 

Canny算子B站讲解:https://space.bilibili.com/580742386?spm_id_from=333.788.b_765f7570696e666f.1

参考链接:https://www.cnblogs.com/wj-1314/p/9800272.html

https://www.bilibili.com/video/BV1U4411277i?from=search&seid=16066791906732345516

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pgtn.cn/news/17832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

创建Silverlight自定义启动画面

每一款商业的Silverlight项目&#xff0c;为了体现项目个性化&#xff0c;都会有不同的界面设计&#xff0c;项目UI设计的第一步就是创建个性的自定义启动画面&#xff0c;本文将介绍如何创建Silverlight自定义启动画面&#xff0c;也就是经常说的Splash Screen. Silverlight初…

数字图像处理:滤波

1、中值滤波 2、均值滤波 3、双边滤波 -------------- 下边是基于卷积核滤波的操作&#xff1a; 在图像中滤波的一般操作就是&#xff1a; 有一个原图。有一个滤波核。(其实就是一个滑动窗口)就是结果图。PS&#xff1a;滤波的效果怎么样&#xff0c;完全取决于你这个滤波核…

齐次坐标的理解(1)

1、为什么要引入齐次坐标&#xff0c;齐次坐标的意义 首先百科解读&#xff1a; 齐次坐标就是将一个原本是n维的向量用一个n1维向量来表示&#xff0c;是指一个用于投影几何里的坐标系统&#xff0c;如同用于欧氏几何里的笛卡儿坐标一般。 以下内容是对这个链接的翻译&#x…

齐次坐标的理解(2)

接上篇文章齐次坐标的理解&#xff08;1&#xff09;&#xff1a;https://blog.csdn.net/m0_37957160/article/details/119549709 “齐次坐标表示是计算机图形学的重要手段之一&#xff0c;它既能够用来明确区分向量和点&#xff0c;同时也更易用于进行仿射&#xff08;线性&a…

OpenCV中的二进制鲁棒独立基本特征——BRIEF

OpenCV中的二进制鲁棒独立基本特征——BRIEF 1. 效果图2. 源码参考这篇博客将介绍OpenCV中的二进制鲁棒独立基本特征。BRIEF是一种更快的特征描述符计算和匹配方法。它还提供了较高的识别率,除非存在较大的面内旋转。 BRIEF Binary Robust Independent Elementary Features 二…

相机标定:(1)相机模型

之前在进行标定时只是简单的会使用&#xff0c;调用OpenCV里边的函数&#xff0c;完成标定即可。并没有做过多深入的理解&#xff0c;今天趁着course学习把标定详细的记录一下&#xff0c;以下完全是个人理解如果有不对的地方欢迎批评指正。 公式推导见标定2&#xff08;2&…

.NET 4.0 Interop新特性ICustomQueryInterface (转载)

.NET 4.0 Interop新特性ICustomQueryInterface 在.NET Framework v4.0发布的新功能中&#xff0c;在名字空间System.Runtime.InteropServices新增加了一个叫做ICustomQueryInterface的Interface, 顾名思义&#xff0c;这个Interface的功能就是使得用户可以自己控制QueryInterf…

相机标定(1)

理解相机标定就要想明白相机模型,成像原理(小孔成像)。 相机标定一共分为两个部分: (1)在进行精度较高的测量时,需要校正畸变即图像的畸变矫正 !(是自身的) (2)相机和机器人之间标定 =手眼标定!