《opencv实用探索·十一》opencv之Prewitt算子边缘检测,Roberts算子边缘检测和Sobel算子边缘检测

2023-12-06 22:28

本文主要是介绍《opencv实用探索·十一》opencv之Prewitt算子边缘检测,Roberts算子边缘检测和Sobel算子边缘检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、前言

边缘检测:
图像边缘检测是指在图像中寻找灰度、颜色、纹理等变化比较剧烈的区域,它们可能代表着物体之间的边界或物体内部的特征。边缘检测是图像处理中的一项基本操作,可以用于人脸识别、物体识别、图像分割等多个领域。

边缘检测实质上是计算当前点和周围点灰度的差别。

图像边缘检测流程主要分为以下几个步骤:
(1)读取待处理图像;
(1)图像滤波,例如使用高斯滤波器,平滑图像,去除噪声;
(2)计算图像中每个像素点的梯度强度和方向;
(3)应用非极大值抑制(Non-Maximum Suooression),保留梯度方向上的局部最大值,抑制非边缘点,消除边缘检测带来的杂散响应;
(4)应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘,即将梯度幅值映射到两个阈值,根据梯度值高于高阈值或在高低阈值之间的情况,将像素标记为强边缘、弱边缘或非边缘。
(5)边缘连接,通过连接相邻的强边缘像素和与之相连的弱边缘像素,形成最终的边缘图像;
(6)显示结果。

在介绍各种边缘检测算子之前先简单阐述下怎么寻找边缘。

下面左图是一张黑白相间的图,右图是左图的每个像素的灰度值
在这里插入图片描述
我们设定一个卷积核如下(关于卷积的介绍请看之前的文章):
在这里插入图片描述
原图在通过卷积核进行卷积计算后得到的图像如下:
可以看到原图在卷积运算后黑色向白色突变的边缘被很好的保留了下来,因此可以通过这个卷积核找到图像中垂直的边缘。
在这里插入图片描述
同理,如果我们用下面的卷积核也可以找到图像中水平的边缘。
在这里插入图片描述
卷积运算后:
在这里插入图片描述

2、Prewitt算子边缘检测
如果我们把上面两个卷积核组合起来再对图像进行卷积便可以同时找到图像中水平和垂直的边缘,这种卷积核就是prewitt算子。
在这里插入图片描述

标准的 Prewitt 边缘检测算子由以下两个卷积核组成。
在这里插入图片描述
下面是用prewitt算子进行边缘检测的案例:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace cv;int main() {// 读取图像Mat image = imread("your_image.jpg", IMREAD_GRAYSCALE);// 定义Prewitt算子Mat prewitt_x = (Mat_<float>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);Mat prewitt_y = (Mat_<float>(3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1);// 对图像应用Prewitt算子Mat edges_x, edges_y;filter2D(image, edges_x, CV_64F, prewitt_x);filter2D(image, edges_y, CV_64F, prewitt_y);// 计算梯度幅值和方向Mat gradient_magnitude, gradient_direction;magnitude(edges_x, edges_y, gradient_magnitude);phase(edges_x, edges_y, gradient_direction, true);// 归一化梯度幅值cv::normalize(gradient_magnitude, gradient_magnitude, 0, 1, cv::NORM_MINMAX);// 显示结果imshow("Original Image", image);  //原灰度图imshow("Gradient Magnitude", gradient_magnitude);  //prewitt算子边缘检测图waitKey(0);destroyAllWindows();return 0;
}

代码解读:
(1)在代码中我们先分别定义一个水平方向和垂直方向的prewitt算子edges_x和edges_y
(2)filter2D是对图像进行卷积操作,即获取prewitt算子与原图像卷积后的图像edges_x和edges_y
(3)magnitude 函数的主要用途是计算两个输入数组的逐元素平方和的平方根。在图像处理中,常常用于计算图像中每个像素点的梯度幅值。相位(Phase)在图像处理中通常指的是梯度的方向(边缘方向)。在梯度计算中,梯度向量的方向表示图像在该点上灰度变化最快的方向。在梯度计算中,通常使用 magnitude 函数计算梯度的幅值,使用 phase 函数计算梯度的方向。这两个信息一起构成了梯度向量,提供了有关图像局部变化的重要信息。
(4)最后归一化梯度幅值图像,因为64位图像显示范围为0-1。

最后效果如下(左边是原灰度图,右边是边缘检测出的图像):
在这里插入图片描述

3、Roberts算子
常用来处理具有陡峭的低噪声图像,当图像边缘接近于正45度或负45度时,该算法处理效果更理想。其缺点是对边缘的定位不太准确,提取的边缘线条较粗。

下图左边为水平方向Roberts算子,也称正对角算子。右边为垂直方向Roberts算子,也称斜对角算子。
在这里插入图片描述
下面是Roberts算子的使用案例:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>int main() {// 生成一个简单的图像cv::Mat image = cv::Mat::zeros(100, 100, CV_8U);cv::rectangle(image, cv::Rect(20, 20, 60, 60), cv::Scalar(255), cv::FILLED);// 定义Sobel算子cv::Mat sobel_x = (cv::Mat_<float>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);cv::Mat sobel_y = (cv::Mat_<float>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);// 应用Sobel算子cv::Mat edges_x, edges_y;cv::filter2D(image, edges_x, CV_64F, sobel_x);cv::filter2D(image, edges_y, CV_64F, sobel_y);// 计算梯度幅值和方向cv::Mat gradient_magnitude, gradient_direction;cv::magnitude(edges_x, edges_y, gradient_magnitude);cv::phase(edges_x, edges_y, gradient_direction, true);  // true 表示计算角度的弧度值// 归一化梯度方向到[0, 1]范围cv::normalize(gradient_direction, gradient_direction, 0, 1, cv::NORM_MINMAX);// 显示结果cv::imshow("Original Image", image);cv::imshow("Gradient Magnitude", gradient_magnitude);cv::imshow("Gradient Direction", gradient_direction);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

最后效果如下(左边是原灰度图,右边是边缘检测出的图像):
在这里插入图片描述

4、Sobel算子边缘检测
Sobel算子在Prewitt算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。但Sobel算子并不是基于图像灰度进行处理的,因为Sobel算子并没有严格地模拟人的视觉生理特性,因此图像轮廓的提取有时并不能让人满意。当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。

它的水平和垂直方向的卷积核如下:
在这里插入图片描述
接口说明:

void cv::Sobel(InputArray src,OutputArray dst,int ddepth,int dx,int dy,int ksize = 3,double scale = 1,double delta = 0,int borderType = cv::BORDER_DEFAULT
);

src: 输入图像。可以是单通道(灰度图)或多通道图像。
dst: 输出图像,梯度的计算结果将存储在这里。
ddepth: 输出图像的深度,通常使用 CV_64F 或 CV_32F 表示。
dx: x方向上的导数阶数,设为1表示在水平方向上进行操作。
dy: y方向上的导数阶数,设为1表示在垂直方向上进行操作。
ksize: Sobel核的大小。默认为 3,表示一个 3x3 的核。通常使用奇数值。
scale: 可选的比例因子,用于调整梯度的幅值,也表示对比度。
delta: 可选的偏移值,用于调整输出图像的亮度。
borderType: 边界处理类型,可以使用 cv::BORDER_DEFAULT 或其他合适的边界处理标志。

Sobel算子边缘检测案例:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>int main() {// 读取图像cv::Mat image = cv::imread("your_image.jpg", cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr << "Error: Could not read the image." << std::endl;return -1;}// 应用Sobel算子cv::Mat edges_x, edges_y;cv::Sobel(image, edges_x, CV_64F, 1, 0, 3); // 1表示在水平方向上进行操作cv::Sobel(image, edges_y, CV_64F, 0, 1, 3); // 1表示在垂直方向上进行操作// 计算梯度幅值cv::Mat gradient_magnitude;cv::magnitude(edges_x, edges_y, gradient_magnitude);// 归一化梯度方向到[0, 1]范围cv::normalize(gradient_magnitude, gradient_magnitude, 0, 1, cv::NORM_MINMAX);// 显示结果cv::imshow("Original Image", image);cv::imshow("Sobel Edges X", edges_x);cv::imshow("Sobel Edges Y", edges_y);cv::imshow("Gradient Magnitude", gradient_magnitude);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

在这里插入图片描述

在这里插入图片描述

这篇关于《opencv实用探索·十一》opencv之Prewitt算子边缘检测,Roberts算子边缘检测和Sobel算子边缘检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/463562

相关文章

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测

PostgreSQL中rank()窗口函数实用指南与示例

《PostgreSQL中rank()窗口函数实用指南与示例》在数据分析和数据库管理中,经常需要对数据进行排名操作,PostgreSQL提供了强大的窗口函数rank(),可以方便地对结果集中的行进行排名... 目录一、rank()函数简介二、基础示例:部门内员工薪资排名示例数据排名查询三、高级应用示例1. 每

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解