8.4Prewitt算子边缘检测

基本原理

Prewitt算子是一种用于边缘检测的经典算子,它通过计算图像中像素值的(一阶导数)梯度来检测边缘。Prewitt算子通常包括两个3x3的卷积核,一个用于检测水平方向上的边缘,另一个用于检测垂直方向上的边缘。

示例代码1

使用OpenCV C++实现Prewitt算子

以下是一个使用OpenCV C++实现Prewitt算子边缘检测的示例代码:

#include <opencv2/opencv.hpp>
#include <iostream>int main(int argc, char** argv)
{if (argc != 2) {std::cout << "Usage: " << argv[0] << " <Image Path>" << std::endl;return -1;}// 读取图像cv::Mat src = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);if (!src.data) {std::cout << "Error: Image cannot be loaded!" << std::endl;return -1;}// 创建输出图像cv::Mat grad_x, grad_y, abs_grad_x, abs_grad_y, combined_grad;// 定义Prewitt算子的卷积核cv::Mat kernel_x = (cv::Mat_<double>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);cv::Mat kernel_y = (cv::Mat_<double>(3, 3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);// 对图像应用Prewitt算子cv::filter2D(src, grad_x, CV_64F, kernel_x);cv::filter2D(src, grad_y, CV_64F, kernel_y);// 转换为8位无符号整型cv::convertScaleAbs(grad_x, abs_grad_x);cv::convertScaleAbs(grad_y, abs_grad_y);// 合并梯度图像cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, combined_grad);// 显示原始图像和边缘检测后的图像cv::namedWindow("Original Image", cv::WINDOW_AUTOSIZE);cv::imshow("Original Image", src);cv::namedWindow("Prewitt X Gradient", cv::WINDOW_AUTOSIZE);cv::imshow("Prewitt X Gradient", abs_grad_x);cv::namedWindow("Prewitt Y Gradient", cv::WINDOW_AUTOSIZE);cv::imshow("Prewitt Y Gradient", abs_grad_y);cv::namedWindow("Combined Gradient", cv::WINDOW_AUTOSIZE);cv::imshow("Combined Gradient", combined_grad);cv::waitKey();return 0;
}代码解释
1.读取图像:从命令行参数读取图像路径,并将其加载为灰度图像。
2.定义卷积核:定义Prewitt算子的两个3x3卷积核,一个用于水平方向,一个用于垂直方向。
3.应用卷积核:使用cv::filter2D函数对图像应用Prewitt算子的卷积核,分别计算水平方向和垂直方向上的梯度。
4.转换为8位图像:由于卷积操作可能会产生负值,因此需要使用cv::convertScaleAbs函数将梯度图像转换为8位无符号整型图像。
5.合并梯度图像:使用cv::addWeighted函数将水平方向和垂直方向上的梯度图像合并成一个图像。
6.显示结果:使用cv::imshow函数分别显示原始图像、水平方向梯度图像、垂直方向梯度图像以及合并后的梯度图像。注意事项
数据类型:在进行卷积操作时,通常选择CV_64F作为中间结果的数据类型,以避免溢出。但在显示图像之前,需要将其转换为CV_8U。
边界处理:卷积操作可能会导致边界上的像素值不准确。在实际应用中,可以通过填充边界来解决这个问题。
参数调整:可以根据实际需求调整卷积核的大小和权重,以优化边缘检测的效果。

运行结果1

​​​​​​​

示例代码2

以下是使用OpenCV C++实现Prewitt算子进行边缘检测的示例代码:

#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;// 定义Prewitt算子掩膜
static const float prewittHorizontal[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};
static const float prewittVertical[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};void detectEdgesWithPrewitt(const Mat &src, Mat &horizontal, Mat &vertical, Mat &magnitude) {Mat kernelHorizontal = Mat(3, 3, CV_32F, prewittHorizontal);Mat kernelVertical = Mat(3, 3, CV_32F, prewittVertical);// 水平方向的边缘检测filter2D(src, horizontal, CV_32F, kernelHorizontal);// 垂直方向的边缘检测filter2D(src, vertical, CV_32F, kernelVertical);// 计算边缘强度magnitude = sqrt(horizontal.mul(horizontal) + vertical.mul(vertical));// 将结果转换为8位无符号整数convertScaleAbs(magnitude, magnitude);
}int main(int argc, char** argv) {if (argc != 2) {cout << "Usage: ./PrewittEdgeDetection <Image Path>" << endl;return -1;}// 加载图像Mat img = imread(argv[1], IMREAD_GRAYSCALE);if (!img.data) {cout << "Error opening image" << endl;return -1;}// 初始化输出矩阵Mat horizontal, vertical, magnitude;// 执行Prewitt边缘检测detectEdgesWithPrewitt(img, horizontal, vertical, magnitude);// 显示结果imshow("Original Image", img);imshow("Prewitt Horizontal", horizontal);imshow("Prewitt Vertical", vertical);imshow("Magnitude", magnitude);waitKey(0);destroyAllWindows();return 0;
}代码解释
1. 定义Prewitt算子掩膜: 使用静态数组来定义Prewitt算子的两个掩膜。
2. 边缘检测: 使用 filter2D 函数分别计算水平方向和垂直方向上的边缘。
3. 计算边缘强度: 通过计算水平方向和垂直方向边缘的平方和的平方根来得到边缘强度。
4. 转换数据类型: 使用 convertScaleAbs 函数将浮点型数据转换为8位无符号整数,以便于显示。
5. 显示结果: 使用 imshow 函数显示原始图像、水平方向边缘、垂直方向边缘以及边缘强度。注意事项
•数据类型: 在计算过程中,我们使用了 CV_32F 类型来保持精度,但在最后为了显示结果,需要将数据转换为 CV_8U 类型。
•噪声处理: Prewitt算子对噪声比较敏感,因此在实际应用中,通常会对图像进行适当的预处理(如高斯滤波)来减少噪声的影响。

运行结果2

实验代码3

 #include "pch.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui_c.h>
using namespace cv;
using namespace std;
//#pragma comment(lib,"opencv_world450d.lib")void getPrewitt_oper(cv::Mat& getPrewitt_horizontal, cv::Mat& getPrewitt_vertical, cv::Mat& getPrewitt_Diagonal1, cv::Mat& getPrewitt_Diagonal2) {//水平方向getPrewitt_horizontal = (cv::Mat_<float>(3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1);//垂直方向getPrewitt_vertical = (cv::Mat_<float>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);//对角135°getPrewitt_Diagonal1 = (cv::Mat_<float>(3, 3) << 0, 1, 1, -1, 0, 1, -1, -1, 0);//对角45°getPrewitt_Diagonal2 = (cv::Mat_<float>(3, 3) << -1, -1, 0, -1, 0, 1, 0, 1, 1);//逆时针反转180°得到卷积核cv::flip(getPrewitt_horizontal, getPrewitt_horizontal, -1);cv::flip(getPrewitt_vertical, getPrewitt_vertical, -1);cv::flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1, -1);cv::flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2, -1);
}void edge_Prewitt(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst3, cv::Mat& dst4, cv::Mat& dst, int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT) {//获取Prewitt算子cv::Mat getPrewitt_horizontal;cv::Mat getPrewitt_vertical;cv::Mat getPrewitt_Diagonal1;cv::Mat getPrewitt_Diagonal2;getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2);//卷积得到水平方向边缘cv::filter2D(src, dst1, ddepth, getPrewitt_horizontal, cv::Point(-1, -1), delta, borderType);//卷积得到4垂直方向边缘cv::filter2D(src, dst2, ddepth, getPrewitt_vertical, cv::Point(-1, -1), delta, borderType);//卷积得到45°方向边缘cv::filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, cv::Point(-1, -1), delta, borderType);//卷积得到135°方向边缘cv::filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, cv::Point(-1, -1), delta, borderType);//边缘强度(近似)cv::convertScaleAbs(dst1, dst1); //求绝对值并转为无符号8位图cv::convertScaleAbs(dst2, dst2);cv::convertScaleAbs(dst3, dst3); //求绝对值并转为无符号8位图cv::convertScaleAbs(dst4, dst4);dst = dst1 + dst2;
}int main() {cv::Mat src = cv::imread("2.jpeg");if (src.empty()){return -1;}if (src.channels() > 1) cv::cvtColor(src, src, CV_RGB2GRAY);cv::Mat dst, dst1, dst2, dst3, dst4;//注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0edge_Prewitt(src, dst1, dst2, dst3, dst4, dst, CV_32F);cv::namedWindow("src", CV_WINDOW_NORMAL);imshow("src", src);cv::namedWindow("水平边缘", CV_WINDOW_NORMAL);imshow("水平边缘", dst1);cv::namedWindow("垂直边缘", CV_WINDOW_NORMAL);imshow("垂直边缘", dst2);cv::namedWindow("45°边缘", CV_WINDOW_NORMAL);imshow("45°边缘", dst3);cv::namedWindow("135°边缘", CV_WINDOW_NORMAL);imshow("135°边缘", dst4);cv::namedWindow("边缘强度", CV_WINDOW_NORMAL);imshow("边缘强度", dst);cv::waitKey(0);return 0;
}

运行结果3

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

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

相关文章

深入理解数据分析的使用流程:从数据准备到洞察挖掘

数据分析是企业和技术团队实现价值的核心。 5 秒内你能否让数据帮你做出决策&#xff1f; 通过本文&#xff0c;我们将深入探讨如何将原始数据转化为有意义的洞察&#xff0c;帮助你快速掌握数据分析的关键流程。 目录 数据分析的五个核心步骤1. 数据获取常用数据获取方式 2. 数…

CentOS7更换阿里云yum更新源

目前CentOS内置的更新安装源经常报错无法更新&#xff0c;或者速度不够理想&#xff0c;这个时候更换国内的镜像源就是一个不错的选择。 备份内置更新源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 下载阿里云repo源&#xff08;需要系统…

Mysql InnoDB 存储引擎简介

InnoDB 存储引擎是 Mysql 的默认存储引擎&#xff0c;它是由 Innobase Oy 公司开发的 Mysql 为什么默认使用 InnoDB 存储引擎 InnoDB 是一款兼顾高可靠性和高性能的通用存储引擎 在 Mysql 5.5 版本之前&#xff0c;默认是使用 MyISAM 存储引擎&#xff0c;在 5.5 及其之后版…

监控系列之-prometheus部署说明

一、Prometheus介绍 Prometheus是一款开源的监控系统&#xff0c;主要用于收集、存储和查询时间序列数据&#xff0c;以便于对系统进行监控和分析Prometheus的架构由四个主要组件组成&#xff1a; 1、Prometheus Server &#xff1a;Prometheus Server是Prometheus的核心组件&a…

一步一步自制py脚本并且并且修改为exe可执行文件教学外附带SHA-1解密exe文件资源

第一步&#xff1a;安装 Python 下载 Python&#xff1a;访问 Python 官网 下载并安装最新版本的 Python。安装时选择添加到环境变量 PATH&#xff1a;在安装过程中&#xff0c;确保勾选“Add Python to PATH”选项。 第二步&#xff1a;编写 Python 脚本 创建一个新的 Pyth…

人脸防伪检测系统源码分享

人脸防伪检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

✔2848. 与车相交的点

代码实现&#xff1a; 方法一&#xff1a;哈希表 #define fmax(a, b) ((a) > (b) ? (a) : (b))int numberOfPoints(int **nums, int numsSize, int *numsColSize) {int hash[101] {0};int max 0;for (int i 0; i < numsSize; i) {max fmax(max, nums[i][1]);for …

Spring4-IoC3-手写IoC

Spring框架的IoC是基于Java反射机制实现的 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff0c;这种动态获取信息以及动态调用对象方法的功…

学习大数据DAY57 新的接口配置

作业  完成 API 接口和文件的接入, 并部署到生产调度平台, 每个任务最后至少 要有两条 不报错 的日志, 报错就驳回作业  作业不需要复制日志 API Appliation Program Interface 应用程序接口 > JSON 的地址 客户需求: 把 https://zhiyun.pub:9099/site/c-class…

【QT】定时器使用

文章目录 关于 Qt 定时器使用的注意细节总结实例-检查工具使用周期时间是否合理UI设计头文件 remind.h源文件 remind.cpp实现效果 关于 Qt 定时器使用的注意细节总结 一、创建与初始化 使用 QTimer 类来创建定时器。可以在构造函数中指定父对象&#xff0c;确保定时器在正确的…

电子电气架构——中央计算的软件定义汽车架构

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

台风,也称为热带气旋,是一种在热带海洋上形成的强烈风暴系统。台风的形成需要满足以下几个条件:

台风&#xff0c;也称为热带气旋&#xff0c;是一种在热带海洋上形成的强烈风暴系统。台风的形成需要满足以下几个条件&#xff1a; 1. **温暖的海水**&#xff1a;台风通常在海面温度至少达到26.5C&#xff08;79.7F&#xff09;的海域形成&#xff0c;因为温暖的海水能够提供…

XShell快速连接虚拟机(Ubuntu系统)

目录 前言 一 (XShell)(虚拟机 )(Ubuntu)下载 二 虚拟机的ip查找 三 虚拟机中安装连接环境 四 开启ssh-server服务 五 验证是Ubuntu是否开启ssh-server服务 六 连接XShell软件 前言 对于刚开始探索 Linux 世界的新手来说&#xff0c;拥有一台自己的服务器可能并不现实。幸运的…

学习大数据DAY58 增量抽取数据表

作业 1 SQL 优化的常见写法有哪些 - 面试经常被问 使用索引&#xff1a;合理创建和使用索引是提高查询效率的关键。索引可以加速数据的检 索速度&#xff0c;但是索引也会占用额外的存储空间&#xff0c;并且在插入、删除和更新操作时会 有额外的开销。 避免全表扫描&…

【ARM】中断术语介绍

外设产生中断给到gic&#xff0c;gic通过内部判断此中断是FIQ还是IRQ&#xff0c;这个过程就称为assert&#xff08;断言&#xff09; 此中断被发到哪里面去叫target cpu跳转到此中断的中断向量表中叫做taken 整个过程就做routing distribute决定将中断发给哪个cpu&#xff08…

【STM32】DAC数字模拟转换

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 前言 DAC简介 DAC配置 DAC时钟使能 GPIO初始化 DAC配置 DAC使能 读写DAC值 驱动代码 MyDAC.h MyDAC.c main.c 前言 大容量的STM32F101xx和STM32F103xx产品才有DAC外设 大容量…

基于SpringBoot的在线考试系统【附源码】

基于SpringBoot的在线考试系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概述 4.2系统功能结构设计 4.3.2 数据库表结构设计 5 系统实现 5.1管理员功能介绍 5.1.1管理员登录 5.1.2 试卷管理 5.1.3 公告信息管理 5.1.…

_Array类,类似于Vector,其实就是_string

例子&#xff1a; using namespace lf; using namespace std;int main() {_Array<int> a(10, -1);_Array<_string> s { _t("one"), _t("two") };_pcn(a);_pcn(s);} 结果&#xff1a; 源代码_Array.h&#xff1a; /***********************…

基础物理-直线运动2

2-1 位置、位移和平均速度 位置与位移 为了确定物体的位置&#xff0c;通常需要相对于某个参考点来测量&#xff0c;这个参考点通常是某个坐标轴的原点&#xff08;或零点&#xff09;&#xff0c;如图 2-1 中的 x 轴。坐标轴的正方向是坐标增大的方向&#xff0c;在图 2-1 中…

掌握远程管理的艺术:揭秘Python的pywinrm库

文章目录 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Python的pywinrm库 &#x1f525;背景&#xff1a;为何选择pywinrm&#xff1f;pywinrm库简介安装pywinrm库简单库函数使用方法场景应用常见问题与解决方案总结 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Py…