OpenCV--图像边缘检测

在计算机视觉和图像处理领域,边缘检测是极为关键的技术。边缘作为图像中像素值发生急剧变化的区域,承载了图像的重要结构信息,在物体识别、图像分割、目标跟踪等众多应用场景中发挥着核心作用。OpenCV 作为强大的计算机视觉库,提供了丰富且高效的边缘检测算法。本文将深入探讨常见边缘检测算法的原理,并结合 OpenCV 的代码示例,助力读者深入理解与运用边缘检测技术。

一、边缘检测简介

边缘检测旨在识别和提取图像中物体的边界,通过检测图像中像素值的变化,标记出图像中明显的边缘部分。不同类型的图像边缘可能对应不同的物体边界、纹理变化或光照变化。在实际应用中,良好的边缘检测结果能大幅简化后续图像处理任务,提高算法的效率和准确性。

二、Sobel 算子

1. 原理

Sobel 算子是一种常用的边缘检测算法,它基于图像中像素的梯度来检测边缘。该算法分别计算图像在水平方向(X 方向)和垂直方向(Y 方向)的梯度,通过近似计算一阶偏导数来获取梯度幅值和方向。具体来说,Sobel 算子使用两个卷积核,一个用于检测水平方向的边缘,另一个用于检测垂直方向的边缘。以 3x3 的 Sobel 核为例,水平方向核为\(\begin{bmatrix}-1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1\end{bmatrix}\),垂直方向核为\(\begin{bmatrix}-1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1\end{bmatrix}\)。通过对图像进行卷积运算,得到水平和垂直方向的梯度值,再根据两者计算梯度幅值和方向,以确定边缘位置。由于 Sobel 算子在计算梯度时考虑了邻域像素的加权平均,对噪声有一定的抑制能力。

2. OpenCV 实现

在 OpenCV 中,使用cv2.Sobel()函数实现 Sobel 边缘检测。该函数的第一个参数为输入图像,第二个参数为输出图像的深度,第三个参数为 X 方向的导数阶数,第四个参数为 Y 方向的导数阶数,此外还可指定卷积核的大小等参数。下面是使用 Sobel 算子进行边缘检测的示例代码:

import cv2import numpy as npimport matplotlib.pyplot as plt# 读取图像并转换为灰度图img = cv2.imread('test.jpg', 0)# 计算X方向的梯度sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = 5)sobelx = np.uint8(np.absolute(sobelx))# 计算Y方向的梯度sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = 5)sobely = np.uint8(np.absolute(sobely))# 计算梯度幅值sobelxy = cv2.addWeighted(cv2.convertScaleAbs(sobelx), 0.5, cv2.convertScaleAbs(sobely), 0.5, 0)# 显示结果plt.subplot(141), plt.imshow(img, cmap = 'gray'), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(142), plt.imshow(sobelx, cmap = 'gray'), plt.title('Sobel X')plt.xticks([]), plt.yticks([])plt.subplot(143), plt.imshow(sobely, cmap = 'gray'), plt.title('Sobel Y')plt.xticks([]), plt.yticks([])plt.subplot(144), plt.imshow(sobelxy, cmap = 'gray'), plt.title('Sobel XY')plt.xticks([]), plt.yticks([])plt.show()

三、Scharr 算子

1. 原理

Scharr 算子同样用于计算图像的梯度,本质上是 Sobel 算子的改进版本。在 Sobel 算子中,当卷积核较小时,对图像细节的检测能力有限。Scharr 算子使用固定的 3x3 卷积核,在计算梯度时,能更精确地逼近导数,对图像细节的检测效果优于 Sobel 算子。水平方向的 Scharr 核为\(\begin{bmatrix}-3 & 0 & 3 \\ -10 & 0 & 10 \\ -3 & 0 & 3\end{bmatrix}\),垂直方向的 Scharr 核为\(\begin{bmatrix}-3 & -10 & -3 \\ 0 & 0 & 0 \\ 3 & 10 & 3\end{bmatrix}\),这使得它在检测图像边缘的细微变化时表现更出色。

2. OpenCV 实现

在 OpenCV 中,通过将cv2.Sobel()函数的ksize参数设置为cv2.CV_SCHARR来使用 Scharr 算子。下面是使用 Scharr 算子进行边缘检测的示例:

import cv2import numpy as npimport matplotlib.pyplot as plt# 读取图像并转换为灰度图img = cv2.imread('test.jpg', 0)# 计算X方向的梯度scharrx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = cv2.CV_SCHARR)scharrx = np.uint8(np.absolute(scharrx))# 计算Y方向的梯度scharry = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = cv2.CV_SCHARR)scharry = np.uint8(np.absolute(scharry))# 计算梯度幅值scharrxy = cv2.addWeighted(cv2.convertScaleAbs(scharrx), 0.5, cv2.convertScaleAbs(scharry), 0.5, 0)# 显示结果plt.subplot(141), plt.imshow(img, cmap = 'gray'), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(142), plt.imshow(scharrx, cmap = 'gray'), plt.title('Scharr X')plt.xticks([]), plt.yticks([])plt.subplot(143), plt.imshow(scharry, cmap = 'gray'), plt.title('Scharr Y')plt.xticks([]), plt.yticks([])plt.subplot(144), plt.imshow(scharrxy, cmap = 'gray'), plt.title('Scharr XY')plt.xticks([]), plt.yticks([])plt.show()

四、Laplacian 算子

1. 原理

Laplacian 算子是一种二阶导数算子,通过计算图像的二阶导数来检测边缘。与 Sobel 和 Scharr 算子基于一阶导数不同,Laplacian 算子对图像中的孤立点、线以及边缘的变化更为敏感。其原理是通过对图像进行拉普拉斯运算,找到二阶导数为零的点,这些点通常对应图像的边缘。在实际应用中,常用的 Laplacian 核有\(\begin{bmatrix}0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0\end{bmatrix}\)等。由于 Laplacian 算子对噪声非常敏感,通常在使用前需要对图像进行平滑处理。

2. OpenCV 实现

在 OpenCV 中,使用cv2.Laplacian()函数实现 Laplacian 边缘检测。该函数的第一个参数为输入图像,第二个参数为输出图像的深度。以下是使用 Laplacian 算子进行边缘检测的示例代码:

import cv2import numpy as npimport matplotlib.pyplot as plt# 读取图像并转换为灰度图img = cv2.imread('test.jpg', 0)# 使用高斯滤波对图像进行平滑处理img = cv2.GaussianBlur(img, (3, 3), 0)# 进行Laplacian边缘检测laplacian = cv2.Laplacian(img, cv2.CV_64F)laplacian = np.uint8(np.absolute(laplacian))# 显示结果plt.subplot(121), plt.imshow(img, cmap = 'gray'), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(laplacian, cmap = 'gray'), plt.title('Laplacian')plt.xticks([]), plt.yticks([])plt.show()

五、Canny 边缘检测

1. 原理

Canny 边缘检测是一种被广泛应用的边缘检测算法,它是一种多阶段的算法,旨在检测出图像中真实、清晰的边缘。Canny 算法主要包含以下几个步骤:

  • 高斯滤波:对输入图像进行高斯滤波,去除噪声,减少噪声对边缘检测的干扰。
  • 计算梯度幅值和方向:使用 Sobel 等算子计算图像中每个像素的梯度幅值和方向。
  • 非极大值抑制:在梯度方向上,对每个像素进行检查,仅保留梯度幅值最大的像素,抑制非边缘像素,从而细化边缘。
  • 双阈值检测和边缘连接:设置高、低两个阈值,将梯度幅值大于高阈值的像素确定为强边缘,小于低阈值的像素排除,介于两者之间的像素根据其与强边缘的连接性来确定是否为边缘。

2. OpenCV 实现

在 OpenCV 中,使用cv2.Canny()函数实现 Canny 边缘检测。该函数的第一个参数为输入图像,第二个参数为低阈值,第三个参数为高阈值。示例代码如下:

import cv2import numpy as npimport matplotlib.pyplot as plt# 读取图像并转换为灰度图img = cv2.imread('test.jpg', 0)# 进行Canny边缘检测edges = cv2.Canny(img, 100, 200)# 显示结果plt.subplot(121), plt.imshow(img, cmap = 'gray'), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(edges, cmap = 'gray'), plt.title('Canny Edges')plt.xticks([]), plt.yticks([])plt.show()

六、总结

本文详细介绍了 OpenCV 中的多种边缘检测算法,包括 Sobel 算子、Scharr 算子、Laplacian 算子和 Canny 边缘检测算法。每种算法都有其独特的原理和适用场景,Sobel 和 Scharr 算子基于一阶导数,对噪声有一定抗性且能较好检测明显边缘;Laplacian 算子基于二阶导数,对细节敏感但对噪声也敏感;Canny 算法通过多阶段处理,能检测出更真实、连续的边缘。在实际应用中,需根据图像的特点和处理需求,选择合适的边缘检测算法,以达到最佳的处理效果。

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

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

相关文章

Rollup详解

Rollup 是一个 JavaScript 模块打包工具,专注于 ES 模块的打包,常用于打包 JavaScript 库。下面从它的工作原理、特点、使用场景、配置和与其他打包工具对比等方面进行详细讲解。 一、 工作原理 Rollup 的核心工作是分析代码中的 import 和 export 语句…

Chapter 7: Compiling C++ Sources with CMake_《Modern CMake for C++》_Notes

Chapter 7: Compiling C Sources with CMake 1. Understanding the Compilation Process Key Points: Four-stage process: Preprocessing → Compilation → Assembly → LinkingCMake abstracts low-level commands but allows granular controlToolchain configuration (c…

5分钟上手GitHub Copilot:AI编程助手实战指南

引言 近年来,AI编程工具逐渐成为开发者提升效率的利器。GitHub Copilot作为由GitHub和OpenAI联合推出的智能代码补全工具,能够根据上下文自动生成代码片段。本文将手把手教你如何快速安装、配置Copilot,并通过实际案例展示其强大功能。 一、…

谢志辉和他的《韵之队诗集》:探寻生活与梦想交织的诗意世界

大家好,我是谢志辉,一个扎根在文字世界,默默耕耘的写作者。写作于我而言,早已不是简单的爱好,而是生命中不可或缺的一部分。无数个寂静的夜晚,当世界陷入沉睡,我独自坐在书桌前,伴着…

Logo语言的死锁

Logo语言的死锁现象研究 引言 在计算机科学中,死锁是一个重要的研究课题,尤其是在并发编程中。它指的是两个或多个进程因争夺资源而造成的一种永久等待状态。在编程语言的设计与实现中,如何避免死锁成为了优化系统性能和提高程序可靠性的关…

深入理解矩阵乘积的导数:以线性回归损失函数为例

深入理解矩阵乘积的导数:以线性回归损失函数为例 在机器学习和数据分析领域,矩阵微积分扮演着至关重要的角色。特别是当我们涉及到优化问题,如最小化损失函数时,对矩阵表达式求导变得必不可少。本文将通过一个具体的例子——线性…

real_time_camera_audio_display_with_animation

视频录制 import cv2 import pyaudio import wave import threading import os import tkinter as tk from PIL import Image, ImageTk # 视频录制设置 VIDEO_WIDTH = 640 VIDEO_HEIGHT = 480 FPS = 20.0 VIDEO_FILENAME = _video.mp4 AUDIO_FILENAME = _audio.wav OUTPUT_…

【Pandas】pandas DataFrame astype

Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型 pandas.DataFrame.astype pandas.DataFrame.astype 是一个方法,用于将 DataFrame 中的数据转换为指定的数据类型。这个方法非常…

Johnson

理论 全源最短路算法 Floyd 算法,时间复杂度为 O(n)跑 n 次 Bellman - Ford 算法,时间复杂度是 O(nm)跑 n 次 Heap - Dijkstra 算法,时间复杂度是 O(nmlogm) 第 3 种算法被 Johnson 做了改造,可以求解带负权边的全源最短路。 J…

Exce格式化批处理工具详解:高效处理,让数据更干净!

Exce格式化批处理工具详解:高效处理,让数据更干净! 1. 概述 在数据分析、报表整理、数据库管理等工作中,数据清洗是不可或缺的一步。原始Excel数据常常存在格式不统一、空值、重复数据等问题,影响数据的准确性和可用…

(三十七)Dart 中使用 Pub 包管理系统与 HTTP 请求教程

Dart 中使用 Pub 包管理系统与 HTTP 请求教程 Pub 包管理系统简介 Pub 是 Dart 和 Flutter 的包管理系统,用于管理项目的依赖。通过 Pub,开发者可以轻松地添加、更新和管理第三方库。 使用 Pub 包管理系统 1. 找到需要的库 访问以下网址&#xff0c…

代码随想录算法训练营第三十五天 | 416.分割等和子集

416. 分割等和子集 题目链接:416. 分割等和子集 - 力扣(LeetCode) 文章讲解:代码随想录 视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibi…

HTTP 教程 : 从 0 到 1 全面指南 教程【全文三万字保姆级详细讲解】

目录 HTTP 的请求-响应 HTTP 方法 HTTP 状态码 HTTP 版本 安全性 HTTP/HTTPS 简介 HTTP HTTPS HTTP 工作原理 HTTPS 作用 HTTP 与 HTTPS 区别 HTTP 消息结构 客户端请求消息 服务器响应消息 实例 HTTP 请求方法 各个版本定义的请求方法 HTTP/1.0 HTTP/1.1 …

spring功能汇总

1.创建一个dao接口,实现类;service接口,实现类并且service里用new创建对象方式调用dao的方法 2.使用spring分别获取dao和service对象(IOC) 注意 2中的service里面获取dao的对象方式不用new的(DI) 运行测试: 使用1的方式创建servic…

Vue.js 实现下载模板和导入模板、数据比对功能核心实现。

在前端开发中,数据比对是一个常见需求,尤其在资产管理等场景中。本文将基于 Vue.js 和 Element UI,通过一个简化的代码示例,展示如何实现“新建比对”和“开始比对”功能的核心部分。 一、功能简介 我们将聚焦两个核心功能&…

volatile关键字用途说明

volatile 关键字在 C# 中用于指示编译器和运行时系统,某个字段可能会被多个线程同时访问,并且该字段的读写操作不应被优化(例如缓存到寄存器或重排序),以确保所有线程都能看到最新的值。这使得 volatile 成为一种轻量级…

【区块链安全 | 第三十五篇】溢出漏洞

文章目录 溢出上溢示例溢出漏洞溢出示例漏洞代码代码审计1. deposit 函数2. increaseLockTime 函数 攻击代码攻击过程总结修复建议审计思路 溢出 算术溢出(Arithmetic Overflow),简称溢出(Overflow),通常分…

百度的deepseek与硅基模型的差距。

问题: 已经下载速度8兆每秒,请问下载30G的文件需要多长时间? 关于这个问题。百度的回答如下: ‌30GB文件下载时间计算‌ ‌理论计算‌(基于十进制单位): ‌单位换算‌ 文件大小:3…

车载诊断架构 --- 特殊定义NRC处理原理

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

面试题ing

1、js中set和map的作用和区别? 在 JavaScript 中,Set 和 Map 是两种非常重要的集合类型 1、Set 是一种集合数据结构,用于存储唯一值。它类似于数组,但成员的值都是唯一的,没有重复的值。Set 中的值只能是唯一的,任何…