canny边缘检测
Canny边缘检测算法是一种广泛使用的边缘检测方法,由John F.Canny在1986年提出。它被认为是边缘检测的“黄金标准”,因为它在检测边缘的同时能够很好地抑制噪声,并且能够精确地定位边缘。Canny算法通过一系列步骤来实现鲁棒的边缘检测,以下是其主要步骤的详细介绍:
1.高斯滤波降噪
由于边缘检测对噪声非常敏感,因此在进行边缘检测之前,通常需要对图像进行平滑处理以去除噪声。Canny算法使用高斯滤波器对图像进行平滑处理,以减少噪声的影响。高斯滤波器是一种低通滤波器,它通过卷积操作将图像中的每个像素与其邻域内的像素进行加权平均,从而平滑图像。
2.计算梯度幅值和方向
在图像平滑后,Canny算法计算每个像素点的梯度幅值和方向。这通常通过使用Sobel算子或其他类似的梯度算子来完成。对于每个像素点,计算其在水平方向((G_x))和垂直方向((G_y))的梯度分量,然后使用以下公式计算梯度幅值和方向:
• 梯度幅值:
[
G=\sqrt{G_x2+G_y2}
]
• 梯度方向:
[
\theta=\arctan2(G_y,G_x)
]
梯度幅值表示该像素点处的边缘强度,而梯度方向表示边缘的方向。
3.非极大值抑制
非极大值抑制是一个关键步骤,用于细化边缘。它的目的是去除那些不是局部最大值的梯度值,从而只保留那些可能是边缘的像素。具体来说,对于每个像素点,检查其梯度方向上的邻域像素。如果当前像素的梯度幅值不是其邻域中的最大值,则将其梯度幅值设置为零。这一步骤可以有效地去除边缘周围的弱响应,使得边缘更加清晰。
4.双阈值检测和边缘连接
Canny算法使用两个阈值来区分强边缘和弱边缘:
• 高阈值(High Threshold):用于检测强边缘。
• 低阈值(Low Threshold):用于检测弱边缘。
具体步骤如下:
-
强边缘检测:首先使用高阈值检测强边缘。所有梯度幅值大于高阈值的像素被认为是强边缘。
-
弱边缘检测:然后使用低阈值检测弱边缘。所有梯度幅值大于低阈值但小于高阈值的像素被认为是弱边缘。
-
边缘连接:最后,通过检查弱边缘像素的邻域,如果弱边缘像素与强边缘像素相连,则将其保留为边缘的一部分。否则,将其舍弃。
5.最终边缘图像
经过上述步骤后,最终得到的图像只包含强边缘和通过边缘连接保留下来的弱边缘。这些边缘通常能够很好地表示图像中的物体轮廓和结构。
Canny算法的优点
-
低错误率:Canny算法能够很好地抑制噪声,从而减少误检测的边缘。
-
良好的定位:Canny算法能够精确地定位边缘,使得边缘检测结果更加准确。
-
最小响应:Canny算法通过非极大值抑制和双阈值检测,确保每个边缘只被检测一次,从而减少了边缘的重复检测。
Canny算法的缺点
-
参数选择:Canny算法需要选择高阈值和低阈值,这些参数的选择对最终的边缘检测结果有很大影响。不同的图像可能需要不同的参数设置。
-
计算复杂度:Canny算法涉及多个步骤,包括高斯滤波、梯度计算、非极大值抑制和双阈值检测,这使得其计算复杂度较高。
示例代码(Python+OpenCV)
以下是一个使用Python和OpenCV实现Canny边缘检测的简单示例:
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图像
image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)# 高斯滤波降噪
blurred_image = cv2.GaussianBlur(image, (5, 5), 0)# 计算梯度幅值和方向
sobel_x = cv2.Sobel(blurred_image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(blurred_image, cv2.CV_64F, 0, 1, ksize=3)
gradient_magnitude = np.sqrt(sobel_x**2 + sobel_y**2)
gradient_direction = np.arctan2(sobel_y, sobel_x)# 非极大值抑制
def non_max_suppression(grad_mag, grad_dir):height, width = grad_mag.shapesuppressed = np.zeros_like(grad_mag, dtype=np.uint8)for i in range(1, height - 1):for j in range(1, width - 1):direction = grad_dir[i, j]if ((direction >= -22.5 and direction < 22.5) or(direction >= 157.5 or direction < -157.5)):neighbors = [grad_mag[i, j-1], grad_mag[i, j+1]]elif ((direction >= 22.5 and direction < 67.5) or(direction >= -157.5 and direction < -112.5)):neighbors = [grad_mag[i-1, j+1], grad_mag[i+1, j-1]]elif ((direction >= 67.5 and direction < 112.5) or(direction >= -112.5 and direction < -67.5)):neighbors = [grad_mag[i-1, j], grad_mag[i+1, j]]else:neighbors = [grad_mag[i-1, j-1], grad_mag[i+1, j+1]]if grad_mag[i, j] >= neighbors[0] and grad_mag[i, j] >= neighbors[1]:suppressed[i, j] = grad_mag[i, j]return suppressed# 双阈值检测和边缘连接
def hysteresis_thresholding(grad_mag, low_threshold, high_threshold):strong_edges = grad_mag > high_thresholdweak_edges = (grad_mag >= low_threshold) & (grad_mag <= high_threshold)edges = strong_edges.astype(np.uint8) * 255for i in range(1, grad_mag.shape[0] - 1):for j in range(1, grad_mag.shape[1] - 1):if weak_edges[i, j]:if np.any(strong_edges[i-1:i+2, j-1:j+2]):edges[i, j] = 255return edges# 应用非极大值抑制
suppressed_edges = non_max_suppression(gradient_magnitude, gradient_direction)# 应用双阈值检测和边缘连接
low_threshold = 50
high_threshold = 150
final_edges = hysteresis_thresholding(suppressed_edges, low_threshold, high_threshold)# 显示结果
plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1), plt.imshow(image, cmap='gray'), plt.title('Original Image')
plt.subplot(1, 3, 2), plt.imshow(suppressed_edges, cmap='gray'), plt.title('Non-Max Suppression')
plt.subplot(1, 3, 3), plt.imshow(final_edges, cmap='gray'), plt.title('Final Edges')
plt.show()
总结
Canny边缘检测算法通过一系列步骤(高斯滤波、梯度计算、非极大值抑制和双阈值检测)实现鲁棒的边缘检测。它能够很好地抑制噪声,精确地定位边缘,并且通过边缘连接保留弱边缘。
领域如何判定
在Canny边缘检测算法中,非极大值抑制(Non-Maximum Suppression,NMS)是一个关键步骤,用于细化边缘,保留局部最大梯度值的点,抑制非边缘的点。其目的是使边缘只有一个像素宽,从而提高边缘检测的准确性和清晰度。
非极大值抑制的具体过程
-
梯度方向分类:
在Canny算法中,梯度方向被分为四个主要方向:0°(水平)、45°(对角)、90°(垂直)和135°(对角)。这种分类简化了后续的比较操作。 -
局部比较:
对于每个像素点,根据其梯度方向,选择其梯度方向上的两个邻域像素进行比较。如果当前像素的梯度幅值不是其邻域中的最大值,则将该像素的梯度幅值抑制为0,即认为它不是边缘。
邻域的定义
在非极大值抑制中,“邻域”指的是当前像素点在梯度方向上的相邻像素。具体来说:
• 如果梯度方向为0°(水平),则邻域为当前像素的左右两个像素。
• 如果梯度方向为90°(垂直),则邻域为当前像素的上下两个像素。
• 如果梯度方向为45°或135°(对角),则邻域为当前像素的对角线上的两个像素。
其他角度的处理
对于其他角度(不在上述四个主要方向上),Canny算法通常会将这些角度归类到最近的主要方向上。例如,如果梯度方向为22.5°,则可以将其归类为45°方向进行处理。这样可以简化计算,并确保所有像素点都能被有效地处理。
领域评价
在非极大值抑制中,邻域的定义和选择对于算法的性能至关重要。通过选择梯度方向上的邻域像素进行比较,可以确保只有真正的边缘点被保留下来。这种方法有效地去除了冗余的边缘响应,提高了边缘检测的准确性和鲁棒性。
应用领域
Canny边缘检测算法因其高效性和准确性,在图像处理和计算机视觉领域得到了广泛应用,包括但不限于:
• 物体检测与识别:用于检测图像中的物体轮廓,辅助物体识别。
• 图像分割:通过边缘检测将图像分割成不同的区域。
• 特征提取:提取图像中的关键特征,用于后续的图像分析。
• 机器人视觉:帮助机器人进行环境感知和路径规划。
• 医学图像分析:用于提取病变区域的边缘,辅助医生进行诊断。
Canny算法在这些领域中的应用,不仅提高了图像处理的效率,还增强了边缘检测的准确性,使其成为计算机视觉领域的一个经典算法。
相关文章:
canny边缘检测
Canny边缘检测算法是一种广泛使用的边缘检测方法,由John F.Canny在1986年提出。它被认为是边缘检测的“黄金标准”,因为它在检测边缘的同时能够很好地抑制噪声,并且能够精确地定位边缘。Canny算法通过一系列步骤来实现鲁棒的边缘检测…...

团建 蓝桥杯省a 15
问题描述 小蓝正在和朋友们团建,有一个游戏项目需要两人合作,两个人分别拿到一棵大小为 nn 和 mm 的树,树上的每个结点上有一个正整数权值。 两个人需要从各自树的根结点 1 出发走向某个叶结点,从根到这个叶结点的路径上经过的所…...
【逻辑学导论】1.6 有效性和真实性
当一个演绎论证成功地将结论和前提必然地联系起来,它是有效的。有效性是针对论证的各命题之间的关系而言的。一个论证是有效的,当且仅当它不可能有真前提和假结论,当且仅当其结论是从其前提逻辑必然地推导出来的。因此,有效性永远…...

IDEA 中集成 Maven,配置环境、创建以及导入项目
目录 在 IntelliJ IDEA 中集成 Maven 并配置环境 1. 打开 IDEA 设置 2. 定位 Maven 配置选项 3. 配置 Maven 路径 4. 应用配置 创建 Maven 项目 1. 新建项目 2. 选择项目类型 3. 配置项目信息 4. 确认 Maven 设置 5. 完成项目创建 导入 Maven 项目 1. 打开导入窗口…...

Qt跨屏窗口的一个Bug及解决方案
如果我们希望一个窗口覆盖用户的整个桌面,此时就要考虑用户有多个屏幕的场景(此窗口要横跨多个屏幕),由于每个屏幕的分辨率和缩放比例可能是不同的,Qt底层在为此窗口设置缩放比例(DevicePixelRatio…...
Vue WebSocket简单应用 ws
webSocket应用 <template><div></div> </template><script> import { getToken } from "/utils/auth"; export default {data() {return {url: "",Socket: null, //socket对象lockReconnect: false, //锁定拒绝重连close: …...

快速单机部署ollama v0.5.7 +openwebui(免去网络环境干扰)
1 概述 本文介绍在一台机器上快速部署测试ollama和openwebui,免去国内网络环境的干扰。 2 环境 2.1 环境 版本信息如下: a、操作系统:centos 7.9 c、docker版本:20.10.5-3 3 部署 3.1 安装docker yum install -y yum-util…...
【华为OD-E卷 - 114 找最小数 100分(python、java、c++、js、c)】
【华为OD-E卷 - 找最小数 100分(python、java、c、js、c)】 题目 给一个正整数NUM1,计算出新正整数NUM2,NUM2为NUM1中移除N位数字后的结果,需要使得NUM2的值最小 输入描述 输入的第一行为一个字符串,字…...

快速搭建GPU环境 | docker、k8s中使用gpu
目录 一、裸机部署安装 GPU Driver安装 CUDA Toolkit测试 二、Docker 环境安装 nvidia-container-toolkit配置使用该 runtime 三、 k8s 环境安装 device-plugin安装 GPU 监控 一、裸机部署 裸机中要使用上 GPU 需要安装以下组件: GPU DriverCUDA Toolkit 二者的关…...

VSCode设置——通过ctrl+鼠标滚动改变字体大小(新版本的vs)
"editor.mouseWheelZoom": true 第一步: 第二步:...
【kafka实战】06 kafkaTemplate java代码使用示例
在 Spring Boot 中使用 KafkaTemplate 可以方便地向 Kafka 发送消息。下面为你详细介绍使用步骤和示例代码。 1. 创建 Spring Boot 项目 你可以使用 Spring Initializr(https://start.spring.io/ )来创建一个新的 Spring Boot 项目,添加以下…...

Java 23新特性
文章目录 Java 23新特性一、引言二、Markdown文档注释(JEP 467)示例 三、ZGC:默认的分代模式(JEP 474)1. 为什么要引入分代模式2. 使用分代模式的优势3. 如何启用分代模式 四、隐式声明的类和实例主方法(JE…...

bat脚本实现自动化漏洞挖掘
bat脚本 BAT脚本是一种批处理文件,可以在Windows操作系统中自动执行一系列命令。它们可以简化许多日常任务,如文件操作、系统配置等。 bat脚本执行命令 echo off#下面写要执行的命令 httpx 自动存活探测 echo off httpx.exe -l url.txt -o 0.txt nuc…...

[创业之路-285]:《产品开发管理-方法.流程.工具 》-1- IPD的功能列表以及导入步骤
一、概述: 对于没有IPD(集成产品开发)流程的公司来说,导入IPD需要循序渐进、有序进行,而不是一步到位。这是因为IPD不仅仅是一种新的产品开发流程,它还涉及到公司文化、组织结构、团队协作方式以及思维方式…...
Redis命令:列表模糊删除详解
前言 在Redis中,列表(List)是一种非常常用的数据结构,允许存储多个有序的元素。然而,在实际应用中,可能会遇到需要删除列表中符合某种模式的元素的需求。本文将详细介绍如何在Redis中实现列表的模糊删除。…...

Day36-【13003】短文,数组的行主序方式,矩阵的压缩存储,对称、三角、稀疏矩阵和三元组线性表,广义表求长度、深度、表头、表尾等
文章目录 本次课程内容第四章 数组、广义表和串第一节 数组及广义表数组的基本操作数组的顺序存储方式-借用矩阵行列式概念二维数组C语言对应的函数-通常行主序方式 矩阵的压缩存储对称矩阵和三角矩阵压缩存储后,采用不同的映射函数稀疏矩阵-可以构成三元组线性表三…...

大数据sql查询速度慢有哪些原因
1.索引问题 可能缺少索引,也有可能是索引不生效 2.连接数配置:连接数过少/连接池比较小 连接数过 3.sql本身有问题,响应比较慢,比如多表 4.数据量比较大 -这种最好采用分表设计 或分批查询 5.缓存池大小 可能是缓存问题ÿ…...
文件 I/O 和序列化
文件I/O C#提供了多种方式来读写文件,主要通过System.IO命名空间中的类来实现,下方会列一些常用的类型: StreamReader/StreamWriter:用于以字符为单位读取或写入文本文件。 BinaryReader/BinaryWriter:用于以二进制格…...

机器学习中的关键概念:通过SKlearn的MNIST实验深入理解
欢迎来到我的主页:【Echo-Nie】 本篇文章收录于专栏【机器学习】 1 sklearn相关介绍 Scikit-learn 是一个广泛使用的开源机器学习库,提供了简单而高效的数据挖掘和数据分析工具。它建立在 NumPy、SciPy 和 matplotlib 等科学计算库之上,支持…...

HELLOCTF反序列化靶场全解
level 2 <?php/* --- HelloCTF - 反序列化靶场 关卡 2 : 类值的传递 --- HINT:尝试将flag传递出来~# -*- coding: utf-8 -*- # Author: 探姬 # Date: 2024-07-01 20:30 # Repo: github.com/ProbiusOfficial/PHPSerialize-labs # email: adminhello-ctf.com…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...