OpenCV中的边缘检测

边缘检测是图像处理和计算机视觉中的关键技术之一,旨在识别图像中像素强度发生显著变化的区域,这些区域通常对应于物体的边界或轮廓。边缘检测在机器视觉中具有重要的需求背景,主要体现在以下几个方面:

  1. 图像分割:边缘检测可以帮助将图像分割成不同的区域,便于后续的图像分析和处理。
  2. 物体识别:通过检测物体的边缘,可以提取物体的特征,为物体识别提供基础。
  3. 图像增强:边缘检测可以增强图像中的重要特征,提高图像的清晰度和质量。
  4. 三维重建:在三维重建中,边缘检测可以帮助确定物体的形状和结构。

1.1.2. 应用场景

边缘检测在机器视觉中有着广泛的应用场景,包括但不限于以下几个方面:

  1. 工业检测:用于检测产品表面的缺陷,如裂纹、划痕、凹陷等。
  2. 自动驾驶:用于检测道路、交通标志、车辆和行人等物体的轮廓,辅助自动驾驶系统进行决策。
  3. 医学图像分析:用于识别医学图像中的器官、病变和组织边界,辅助医生进行诊断。
  4. 安防监控:用于检测视频中的异常行为或物体,提高监控系统的智能化水平。
  5. 机器人视觉:用于识别环境中的物体和障碍物,帮助机器人进行导航和避障。

1.2. OpenCV中的实现方法

OpenCV提供了多种边缘检测方法,常用的包括:

  1. Canny 边缘检测
  2. Sobel 算子
  3. Laplacian 算子

1.2.1. Canny 边缘检测

原理及内部流程: Canny 边缘检测是一种多阶段的边缘检测算法,主要包括以下步骤:

  1. 噪声抑制:使用高斯滤波器对图像进行平滑处理,以减少噪声的影响。
  2. 计算梯度:使用Sobel算子计算图像的梯度幅值和方向。
  3. 非极大值抑制:沿着梯度方向,保留局部梯度最大的像素点,抑制其他像素点,有效的去除多余的边缘效应,精确图像的边缘。
  4. 双阈值检测:设置高阈值和低阈值,高于高阈值的像素被认为是强边缘,介于高阈值和低阈值之间的像素被认为是弱边缘。
  5. 边缘连接:通过强边缘像素和与之相邻的弱边缘像素进行连接,形成完整的边缘线。

参数确定及影响

  • 高斯滤波器的参数:通常根据图像的噪声水平选择合适的高斯滤波器参数,如标准差和核大小。
  • 阈值:高阈值和低阈值的选择对边缘检测结果有重要影响。高阈值用于检测强边缘,低阈值用于检测弱边缘。阈值的选择需要根据图像的特点和应用场景进行调整。

1.2.2. Sobel 算子

原理及内部流程: Sobel 算子是一种基于一阶导数的边缘检测算子,通过计算图像在水平和垂直方向的梯度来检测边缘。Sobel 算子使用两个3×3的卷积核,分别计算水平和垂直方向的梯度,然后通过这两个梯度来估计边缘。

参数确定及影响

  • 卷积核大小:通常为3×3,但可以根据需要选择其他大小。
  • 阈值:通过设置阈值来确定边缘像素,阈值的选择需要根据图像的特点和应用场景进行调整。

1.2.3. Laplacian 算子

原理及内部流程: Laplacian 算子是一种基于二阶导数的边缘检测算子,通过对图像进行二阶微分操作来检测边缘。Laplacian 算子可以提供边缘的强度和方向信息。

参数确定及影响

  • 卷积核大小:通常为3×3,但可以根据需要选择其他大小。
  • 阈值:通过设置阈值来确定边缘像素,阈值的选择需要根据图像的特点和应用场景进行调整。、

1.2.4. 在openCV中如何使用

Sobel 算子与Laplacian 算子:这个在之前的高通滤波中已经说明过。

Canny 算子:

edges = cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
  1. image
    • 作用:输入图像,必须是单通道灰度图像
    • 确认方法:如果输入图像是彩色图像,需要先将其转换为灰度图像:Python复制
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  1. threshold1
    • 作用:低阈值,用于滞后阈值处理。
    • 作用机制:用于检测弱边缘。如果梯度幅值低于此阈值,则认为该像素不是边缘。
    • 确认方法
      • 根据经验,可以设置为 50 左右。
      • 通过实验调整,观察边缘检测的效果。通常需要结合高阈值一起调整。
      • 调的较低会保留更多的弱边缘,对于边缘较弱的,可以适当降低低阈值
  1. threshold2
    • 作用:高阈值,用于滞后阈值处理。
    • 作用机制:用于检测强边缘。如果梯度幅值高于此阈值,则认为该像素是强边缘。
    • 确认方法
      • 根据经验,可以设置为 150 左右。
      • 高阈值与低阈值的比值通常在 2:1 到 3:1 之间。例如,低阈值为 50,高阈值为 150 或 100。
      • 对于边缘较复杂的图像,可以适当增加高阈值。
  1. apertureSize
    • 作用:Sobel 算子的卷积核大小,影响梯度计算的精度。
    • 默认值:3
    • 确认方法
      • 如果需要更平滑的边缘,可以尝试更大的值(如 5 或 7)。
      • 值越大,计算复杂度越高,但边缘检测结果可能更平滑。
  1. L2gradient
    • 作用:决定梯度幅值的计算方式。
      • 如果为 True,则使用 L2 范数计算梯度幅值(M=Gx2+Gy2)。
      • 如果为 False,则使用 L1 范数计算梯度幅值(M=∣Gx∣+∣Gy∣)。
    • 默认值False
    • 确认方法
      • 如果对精度要求较高,可以设置为 True
      • 如果对性能要求较高,可以使用默认值 False
# Canny 边缘检测
edges = cv2.Canny(gray_image, 100, 200)

我们可以找一张图片,先高斯滤波,然后Canny检测,再边缘检测,感受一下各参数的改变的Canny边缘检测的影响:

新建文件:UiTest.py 在其中构建下列类

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Sliderclass EdgeDetectionDemo:def __init__(self, image_path):self.image = cv2.imread(image_path)if self.image is None:raise ValueError(f"Failed to load image at path: {image_path}")self.image_gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)# 初始化默认参数self.blur_size = 5self.canny_low = 100self.canny_high = 200self.min_w = 100self.min_h = 100# 创建图像窗口self.fig, (self.ax1, self.ax2, self.ax3) = plt.subplots(1, 3, figsize=(18, 6))self.fig.subplots_adjust(bottom=0.25)  # 调整底部空间以放置滑块# 显示原始图像self.ax1.imshow(cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB))self.ax1.set_title("Original Image")self.ax1.axis('off')# 显示边缘检测和轮廓检测结果self.update_processing()# 创建滑块self.create_sliders()plt.show()def update_processing(self):# 高斯模糊(确保核大小为奇数)blur_size = self.blur_size if self.blur_size % 2 == 1 else self.blur_size + 1blurred = cv2.GaussianBlur(self.image_gray, (blur_size, blur_size), 0)# Canny边缘检测edges = cv2.Canny(blurred, self.canny_low, self.canny_high)# 查找轮廓contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 绘制边缘检测结果self.ax2.clear()self.ax2.imshow(edges, cmap='gray')self.ax2.set_title(f"Canny Edges (Low={self.canny_low}, High={self.canny_high})")self.ax2.axis('off')# 绘制轮廓检测结果contour_img = self.image.copy()valid_contours = []for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)if w > self.min_w and h > self.min_h:cv2.rectangle(contour_img, (x, y), (x+w, y+h), (0, 255, 0), 2)valid_contours.append(cnt)self.ax3.clear()self.ax3.imshow(cv2.cvtColor(contour_img, cv2.COLOR_BGR2RGB))self.ax3.set_title(f"Contours (Min Size: {self.min_w}x{self.min_h})")self.ax3.axis('off')self.fig.canvas.draw_idle()  # 重新绘制图像def create_sliders(self):# 创建滑块ax_blur_size = self.fig.add_axes([0.25, 0.15, 0.65, 0.03])ax_canny_low = self.fig.add_axes([0.25, 0.12, 0.65, 0.03])ax_canny_high = self.fig.add_axes([0.25, 0.09, 0.65, 0.03])ax_min_w = self.fig.add_axes([0.25, 0.06, 0.65, 0.03])ax_min_h = self.fig.add_axes([0.25, 0.03, 0.65, 0.03])self.slider_blur_size = Slider(ax_blur_size, 'Blur Size', 1, 15, valinit=self.blur_size, valstep=2)self.slider_canny_low = Slider(ax_canny_low, 'Canny Low', 0, 300, valinit=self.canny_low, valstep=10)self.slider_canny_high = Slider(ax_canny_high, 'Canny High', 50, 500, valinit=self.canny_high, valstep=10)self.slider_min_w = Slider(ax_min_w, 'Min Width', 50, 500, valinit=self.min_w, valstep=10)self.slider_min_h = Slider(ax_min_h, 'Min Height', 50, 500, valinit=self.min_h, valstep=10)# 绑定滑块事件self.slider_blur_size.on_changed(self.update_slider)self.slider_canny_low.on_changed(self.update_slider)self.slider_canny_high.on_changed(self.update_slider)self.slider_min_w.on_changed(self.update_slider)self.slider_min_h.on_changed(self.update_slider)def update_slider(self, val):self.blur_size = int(self.slider_blur_size.val)self.canny_low = int(self.slider_canny_low.val)self.canny_high = int(self.slider_canny_high.val)self.min_w = int(self.slider_min_w.val)self.min_h = int(self.slider_min_h.val)self.update_processing()

在另外一个文件(learnCV.py)中引用该类

from ImageManipulation import cvTest
from UiTest import EdgeDetectionDemo
def main():# cvTest.TestGrayImage()# cvTest.TestChannelSplite()demo = EdgeDetectionDemo("Cars.jpg")if(__name__=="__main__"):main()
  1. 滤波核大小对弱边缘有影响,滤波核越大,弱边缘越少

 

 

高阈值越高,弱边缘越少

 


极限检测:

上下限和滤波都是0:

 

先逐渐把低阈值拉满:

 

再把高阈值拉满:

 

弱边缘是在持续减少的。

大家可以个人自己多尝试尝试

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【简历优化】性能调优 — 编程性能调优篇

😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文讲解【简历优化】性能调优 — 编程性能调优篇,期待与你一同探索、学习、进步,一起卷起来叭! 目录 一、编程性能调优字符串String 发展优…

深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程

MySQL 作为最流行的关系型数据库之一,其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例,深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程,揭示其底层实现逻辑。 一、SQL…

RNN中远距离时间步梯度消失问题及解决办法

RNN中远距离时间步梯度消失问题及解决办法 RNN 远距离时间步梯度消失问题LSTM如何解决远距离时间步梯度消失问题 RNN 远距离时间步梯度消失问题 经典的RNN结构如下图所示: 假设我们的时间序列只有三段, S 0 S_{0} S0​ 为给定值,神经元没有…

Tomcat理论(Ⅰ)

目录 服务器流程图一览 一、JavaWeb前奏(了解) 1. C/S结构 2. B/S结构 3. 静态网页&动态网页 4.常见的网页 5.Web服务器 知名服务器: ​编辑 二、Tomcat安装(熟练) 1.Tomcat概述 2.Tomcat的作用 3.Tomcat安装 4.Tomcat测试 3.…

如何使用 DeepSeek R1 构建开源 ChatGPT Operator 替代方案

开源大型语言模型(LLMs)的兴起使得创建 AI 驱动的工具比以往任何时候都更容易,这些工具可以与 OpenAI 的 ChatGPT Operator 等专有解决方案相媲美。在这些开源模型中,DeepSeek R1 以其强大的推理能力、自由的可访问性和适应性而脱…

使用Docker Desktop部署GitLab

1. 环境准备 确保Windows 10/11系统支持虚拟化技术(需在BIOS中开启Intel VT-x/AMD-V)内存建议≥8GB,存储空间≥100GB 2. 安装Docker Desktop 访问Docker官网下载安装包安装时勾选"Use WSL 2 instead of Hyper-V"(推荐…

【复习】Java集合

集合概念 集合与数组 数组是固定长度;集合是动态长度的数据结构,需要动态增加或删除元素 数组可以包含基本数据类型和对象;集合只能包含对象 数组可以直接访问元素;集合需要通过迭代器访问元素 线程安全的集合? …

vue3 文件类型传Form Data数据格式给后端

在 Vue 3 中,如果你想将文件(例如上传的 Excel 文件)以 FormData 格式发送到后端,可以通过以下步骤实现。这种方式通常用于处理文件上传,因为它可以将文件和其他数据一起发送到服务器。 首先,创建一个 Vue…

使用 INFINI Console 配置集群监控 Webhook 通知指南

在集群管理中,监控关键指标如CPU、内存、磁盘、JVM等是至关重要的。对于Easysearch及ES生态系统,还需要关注集群本身的指标,例如搜索延迟、集群状态、节点移除等。INFINI Console不仅提供了默认的监控指标,还支持用户自定义监控项…

WPF的页面设计和实用功能实现

目录 一、TextBlock和TextBox 1. 在TextBlock中实时显示当前时间 二、ListView 1.ListView显示数据 三、ComboBox 1. ComboBox和CheckBox组合实现下拉框多选 四、Button 1. 设计Button按钮的边框为圆角,并对指针悬停时的颜色进行设置 一、TextBlock和TextBox…

二级公共基础之数据结构与算法篇(八)排序技术

目录 前言 一、交换类排序 1.冒泡排序法 1. 冒泡排序的思想 2. 冒泡排序的实现步骤 3. 示例 4. 冒泡排序的特点 2.快速排序 1. 快速排序的核心思想 2. 快速排序的实现步骤 3. 示例代码(C语言) 4. 快速排序的特点 二、插入类排序 1. 简单插入排序 1.简单插入排…

记录一次 ALG 的处理过程

前几天朋友找我帮忙,说碰到很大困难了,实际上,不过如此 现象是这样的: FreeSWITCH mod_unimrcp 工作不正常 FS 和 mrcp-server 两边同时抓包,看到的是: sip 流程正常 FS TCP 连接到 mccp-server 失败&…

【Linux网络编程】IP协议格式,解包步骤

目录 解析步骤 1.版本字段(大小:4比特位) 2.首部长度(大小:4比特位)(单位:4字节) 🍜细节解释: 3.服务类型(大小:8比特…

CSDN文章质量分查询系统【赠python爬虫、提分攻略】

CSDN文章质量分查询系统 https://www.csdn.net/qc 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链接-----> https://www.csdn.net/qc <------点击链接 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链…

HTML应用指南:利用GET请求获取全国泸溪河门店位置信息

随着新零售业态的快速发展,门店位置信息的获取变得越来越重要。作为新兴烘焙品牌之一,泸溪河自2013年在南京创立以来,一直坚持“健康美味,香飘世界”的企业使命,以匠人精神打造新中式糕点。为了更好地理解和利用这些数据,本篇文章将深入探讨GET请求的实际应用,并展示如何…

如何在 React 中测试高阶组件?

在 React 中测试高阶组件可以采用多种策略&#xff0c;以下是常见的测试方法&#xff1a; 1. 测试高阶组件返回的组件 高阶组件本身是一个函数&#xff0c;它返回一个新的组件。因此&#xff0c;可以通过测试这个返回的组件来间接测试高阶组件的功能。通常使用 Jest 作为测试…

R语言Stan贝叶斯空间条件自回归CAR模型分析死亡率多维度数据可视化

全文链接&#xff1a;https://tecdat.cn/?p40424 在空间数据分析领域&#xff0c;准确的模型和有效的工具对于研究人员至关重要。本文为区域数据的贝叶斯模型分析提供了一套完整的工作流程&#xff0c;基于Stan这一先进的贝叶斯建模平台构建&#xff0c;帮助客户为空间分析带来…

Casbin 权限管理介绍及在 Go 语言中的使用入门

引言 在现代软件开发过程中&#xff0c;权限管理是一个至关重要的环节&#xff0c;它关系到系统的安全性和用户体验。Casbin 是一个强大的访问控制库&#xff0c;支持多种访问控制模型&#xff0c;如 ACL&#xff08;访问控制列表&#xff09;、RBAC&#xff08;基于角色的访问…

快速入门——第三方组件element-ui

学习自哔哩哔哩上的“刘老师教编程”&#xff0c;具体学习的网站为&#xff1a;10.第三方组件element-ui_哔哩哔哩_bilibili&#xff0c;以下是看课后做的笔记&#xff0c;仅供参考。 第一节 组件间的传值 组件可以有内部Data提供数据&#xff0c;也可由父组件通过prop方式传…

【算法通关村 Day7】递归与二叉树遍历

递归与二叉树遍历青铜挑战 理解递归 递归算法是指一个方法在其执行过程中调用自身。它通常用于将一个问题分解为更小的子问题&#xff0c;通过重复调用相同的方法来解决这些子问题&#xff0c;直到达到基准情况&#xff08;终止条件&#xff09;。 递归算法通常包括两个主要…