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

news2024/11/24 1:56:37

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;
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Streamlit框架的定制化

Streamlit框架的定制化 最近做了一个关于streamlit框架的项目&#xff0c;颇有感触&#xff0c;所以在这里记录一下。 什么是streamlit? Streamlit 是一个python的WEB UI库&#xff0c;它做了高度的封装以便于不懂后前端开发的人员也能轻松构建画面。你可以从官网进行详细的…

你真的掌握结构体了么?结构体习题(C语言)

前言 上一期博客我们学习了结构体的相关知识&#xff08;上期链接&#xff09;&#xff0c;但是学了不练也是不行的&#xff0c;我们今天讲给大家分享两道有点恶心的题目&#xff0c;让大家来加深对结构体的理解&#xff0c;那么话不多说我们现在开始吧&#xff01; 第一题 有…

zabbix 进阶

zabbix的字段发现机制&#xff1a; zabbix客户端主动和服务端联系&#xff0c;将自己的地址和端口发送服务端实现字段添加监控主机。 客户端是主动一方。 缺点&#xff1a;自定义网段中主机数量太多&#xff0c;登记耗时会很久&#xff0c;而且这个自动发现机制不是很稳定。…

Hadoop学习笔记(HDP)-Part.20 安装Flume

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

AIGC+医疗专题:生成式人工智能于医疗健康

今天分享的是AI系列深度研究报告&#xff1a;《AIGC医疗专题&#xff1a;生成式人工智能于医疗健康》。 &#xff08;报告出品方&#xff1a;AREFACT&#xff09; 报告共计&#xff1a;23页 医疗保健中生成性人工智能的崛起: 在承诺与控制之间导航 Generative Al已经历了大规…

Python-代码块缩进详解

python中&#xff0c;if后面没有&#xff08;&#xff09;&#xff0c;执行代码块也没有{} 而是以&#xff1a;为结尾 代码块以缩进的形式书写&#xff1a; a input("请输入一个整数&#xff1a;") if a 1:print(aaaa) print(bbbb)#此时这一行代码就与判断条件无关…

数据结构-02-链表

相比数组&#xff0c;链表是一种稍微复杂一点的数据结构。掌握起来也要比数组稍难一些。这两个非常基础、非常常用的数据结构。 1-链表结构 数组需要一块连续的内存空间来存储&#xff0c;对内存的要求比较高。如果我们申请一个20MB大小的数组&#xff0c;当内存中没有连续的、…

python打包exe,打包好后,启动exe报错找不到paddleocr

目录 1、安装pyinstaller 2、生成脚本文件的.spce文件 3、资源文件配置 4、生成exe文件 5、使用了paddleocr启动exe后报错 6、配置.spce文件 7、重新生成exe文件 8、关于图片找不到的问题 参考&#xff1a;PaddleOCR打包exe--Pyinstaller_paddleocr 打包exe_mjiansun的博…

智能监控/安防监控视频平台EasyCVR下级更新目录表出现离线情况的两种解决方案

GB28181安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备…

esp32使用命令查看芯片flash大小以及PSRAM的大小

在idf.py命令窗口中输入 esptool.py -p COM* flash_id 其中COM*是连接你的esp32芯片的端口号。

打工人副业变现秘籍,某多/某手变现底层引擎-StableDiffusionWebUI界面基本布局和操作

一、界面设置 文生图&#xff1a;根据文本提示生成图像 图生图&#xff1a;图像生成图像&#xff1b;功能很强大&#xff0c;自己在后续使用中探索。 后期处理&#xff1a;图片处理&#xff1b;功能很强大&#xff0c;自己在后续使用中探索。 PNG信息&#xff1a;这是一个快…

“轻松管理视频文件:高效归类与统一重命名“

随着电子设备的普及&#xff0c;我们的视频文件可能来自各种不同的源头&#xff0c;如何高效地管理和查找这些文件成为了一个问题。今天&#xff0c;我们将为您提供一个完美的解决方案——自动归类并统一重命名视频文件。 首先&#xff0c;第一步&#xff0c;我们要进入文件批…

基于openEuler20.03安装openGauss5.0.0及安装DBMind

基于openEuler20.03安装openGauss5.0.0及安装DBMind 一、环境说明二、安装部署三、问题及解决 一、环境说明 虚拟机&#xff1a;VirtualBox操作系统&#xff1a;openEuler20.3LTS &#xff08;x86&#xff09;数据库&#xff1a;openGauss5.0.0 (x86)DBMind&#xff1a;dbmind…

智能优化算法应用:基于学生心理学算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于学生心理学算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于学生心理学算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.学生心理学算法4.实验参数设定5.算法结果…

Esxi6.0 安装web管理界面

安装6.0之后默认是vSphere Client进行远程连接&#xff0c;需要安装客户端&#xff0c;不是太方便。搜索发现还真可以实现web管理&#xff0c;步骤如下&#xff1a; 1、开启esxi的ssh&#xff0c;步骤如下图&#xff1a; 2、下载升级包esxui-signed-7119706.vib&#xff0c;上…

案例四:使用系统存储过程查看相关信息

1、什么是存储过程。 【1】模块化程序设计 【2】执行速度快&#xff0c;效率高 【3】减少网络流量 【4】具有良好的安全性 存储过程分为两类&#xff1a; 1、系统存储过程、2、用户自定义的存储过程 2、若xp_cmdshell作为服务器安全配置的一部分而被关闭&#xff0c;则需要配置…

力扣11.盛最多水的容器

题目描述 思路 用双指针法。 每次向内移动较短的那个板&#xff0c;能带来更大的效益。 代码 class Solution {public int maxArea(int[] height) {int res 0;int i 0,j height.length - 1;while(i < j){res height[i] < height[j] ? Math.max((j - i) * height…

祸害了人民3年的新冠消失了,但有些奇怪现象,让人百思不得其解

真是没想到啊&#xff0c;祸害我们3年的新冠病毒突然就消失了&#xff0c;但是紧接着呢&#xff0c;却有一个非常奇怪的现象出现了&#xff0c;真的是令人百思不得其解&#xff01; 新冠病毒&#xff0c;于2020年的开始&#xff0c;可以说根本就没有任何缓冲期&#xff0c;一开…

BUU SQL COURSE 1

四 发现有登录框&#xff0c;爆破半天也爆破不出来&#xff0c;只能从别的地方下手了 F12一下 发现了一个传参 进去发现id可以传参&#xff0c;sql注入一下试试 前三个都有回显&#xff0c;当id4的时候页面没有回显了&#xff0c;正好验证 了页面 有三个新闻 当order by 3的时…

docker安装及简单使用(Linux版本)

文章目录 前言一、docker安装二、docker命令pull&#xff08;安装镜像&#xff09;images&#xff08;查看镜像&#xff09;run&#xff08;创建容器&#xff09;删除容器exec&#xff08;进入运行中的容器&#xff09;常用命令 总结如有启发&#xff0c;可点赞收藏哟~ 前言 ht…