8.4Prewitt算子边缘检测

news2024/11/15 8:09:45

基本原理

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位无符号,则会导致这些地方为0
	edge_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.coloradmin.cn/o/2139071.html

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

相关文章

【动漫资源管理系统】Java SpringBoot助力,搭建一个高清动漫在线观看网站

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

【插件】【干货】用EPPlus在Unity中读写Excel表

EPPlus是什么我就不说了&#xff0c;你都点进来了肯定知道 几个常用的api 1.index下标都是从1开始的 2.可以读取任意单元格上的任意内容&#xff0c;不需要给excel表写规则 但是如果你写了规则&#xff0c;就需要自己用额外的代码 --- 数据结构去实现 3.打开excel表 ExcelP…

[数据集][目标检测]智慧交通铁路异物入侵检测数据集VOC+YOLO格式802张7类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;802 标注数量(xml文件个数)&#xff1a;802 标注数量(txt文件个数)&#xff1a;802 标注类别…

萤石举办2024清洁机器人新品发布会 多维智能再造行业标杆

导言&#xff1a;作为智慧生活守护者&#xff0c;萤石今日发布了两款清洁机器人&#xff0c;AI扫拖机器人RS20 Pro Ultra 和AI洗地机器人RX30 Max &#xff0c;标志着萤石在智能清洁领域的全新突破。RS20 Pro Ultra基于CutFree 2.0内切割滚刷专利&#xff0c;有效解决毛发缠绕难…

速通GPT:《Improving Language Understanding by Generative Pre-Training》全文解读

文章目录 速通GPT系列几个重要概念1、微调的具体做法2、任务感知输入变换3、判别式训练模型 Abstract概括分析和观点1. 自然语言理解中的数据问题2. 生成预训练和监督微调的结合3. 任务感知输入变换4. 模型的强大性能 Introduction概括分析和观点1. 自然语言理解的挑战在于对标…

探索Python的HTML处理神器:pyquery的魔力

文章目录 探索Python的HTML处理神器&#xff1a;pyquery的魔力背景&#xff1a;为何选择pyquery&#xff1f;pyquery是什么&#xff1f;安装pyquery五个简单的库函数使用方法1. $&#xff1a;选择元素2. .text()&#xff1a;获取文本内容3. .html()&#xff1a;获取HTML内容4. …

SSM框架学习(三、MyBatis实践:提高持久层数据处理效率)

目录 一、Mybatis简介 1.简介 2.持久层框架对比 3.快速入门&#xff08;基于Mybatis3方式&#xff09; 4.ibatis方式的实现和原理 5.ibatis与mybatis之间的关系 二、Mybatis基本使用 1.向 sql 语句传参 &#xff08;1&#xff09;mybatis日志输出配置 &#xff08;2&…

小程序开发设计-第一个小程序:创建小程序项目④

上一篇文章导航&#xff1a; 小程序开发设计-第一个小程序&#xff1a;安装开发者工具③-CSDN博客https://blog.csdn.net/qq_60872637/article/details/142219152?spm1001.2014.3001.5501 须知&#xff1a;注&#xff1a;不同版本选项有所不同&#xff0c;并无大碍。 一、创…

主播和礼品检测系统源码分享

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

SSH软链接后门从入门到应急响应

目录 1. 软链接与SSH软链接后门介绍 1.1 软链接介绍 1.2 SSH软连接后门介绍 2. 如何在已拿下控制权限的主机创建后门 2.1 使用root账户并执行ssh软链接后门命令&#xff1a; 2.2 连接软链接后门测试&#xff1a; 2.3 创建其它账户 ssh软连接后门命令 3. 如何进行应急…

笋丁网页自动回复机器人V3.0.0免授权版源码

笋丁网页机器人一款可设置自动回复&#xff0c;默认消息&#xff0c;调用自定义api接口的网页机器人。 此程序后端语言使用Golang&#xff0c;内存占用最高不超过30MB&#xff0c;1H1G服务器流畅运行。仅支持Linux服务器部署&#xff0c;不支持虚拟主机&#xff0c;请悉知&…

七. 部署YOLOv8检测器-quantization-analysis

目录 前言0. 简述1. 案例运行2. 补充说明3. 量化分析4. 探讨总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第七章—部署YOLOv8检测器&#xff0c;一起来学习…

无限边界:现代整合安全如何保护云

尽管云计算和远程工作得到广泛采用&#xff0c;零信任网络也稳步推广&#xff0c;但边界远未消失。相反&#xff0c;它已被重新定义。就像数学分形的边界一样&#xff0c;现代网络边界现在无限延伸到任何地方。 不幸的是&#xff0c;传统工具在现代无限边界中效果不佳。现代边…

优化算法(三)—模拟退火算法(附MATLAB程序)

模拟退火算法&#xff08;Simulated Annealing, SA&#xff09;是一种基于概率的优化算法&#xff0c;旨在寻找全局最优解。该算法模拟金属退火过程中的物质冷却过程&#xff0c;逐渐降低系统的“温度”以达到全局优化的效果。它特别适用于解决复杂的组合优化问题。 一、模拟退…

深度学习笔记(6)文本分类

深度学习笔记&#xff08;6&#xff09;文本分类 文章目录 深度学习笔记&#xff08;6&#xff09;文本分类一、文本分析与关键词提取1.关键概念1.停用词2 Tf-idf&#xff1a;关键词提取 3.相似度 二、文本分析案例1.数据处理2.分词&#xff1a;实用结巴分词器3.清洗4.TF-IDF5.…

FastText 和 Faiss 的初探了解

概览 大模型目前已经是如火如荼的程度&#xff0c;各个大厂都有推出面向大众的基础大模型&#xff0c;同时诸多行业也有在训练专有大模型&#xff0c;而大模型的发展由来却是经过多年从文本检索生成、深度学习、自然语言处理&#xff0c;在Transformer架构出来后&#xff0c;才…

win11下面graphviz的用法

安装 安装graphviz 2.38版本 控制面板在变量path中增加E:\software\Graphviz\bin example.dot代码 digraph SignalPathway {node [fontname"SimHei"];edge [fontname"SimHei"];// 定义节点形状node [shapecircle];// 定义节点CellA [label"细胞 A&…

第 13 章 兵马未动,粮草先行——InnoDB 统计数据是如何收集的

表的统计数据&#xff1a;SHOW TABLE STATUS LIKE table_name; 索引的统计数据&#xff1a;SHOW INDEX FROM table_name; 13.1 两种不同的统计数据存储方式 InnoDB 提供了两种存储统计数据的方式&#xff1a; 永久性的统计数据。存储在磁盘上&#xff0c;服务器重启之后还在…

nvm安装并配置全局缓存文件

nvm下载&#xff0c;最新版为 1.1.12&#xff1a;Releases coreybutler/nvm-windows GitHub 下载exe&#xff0c;选择指定位置安装即可&#xff0c;安装及配置参考链接&#xff1a;window下安装并使用nvm&#xff08;含卸载node、卸载nvm、全局安装npm&#xff09;-CSDN博客 …

SpringBoot教程(安装篇) | RabbitMQ的安装

SpringBoot教程&#xff08;安装篇&#xff09; | RabbitMQ的安装 一、下载RabbitMQ&#xff08;windows版本&#xff09;1. 先下载 RabbitMQ2. 再下载Erlang3. 开始安装 Erlang4. 为Erlang配置环境变量5、验证安装6. 开始安装 RabbitMQ7. 启用RabbitMQ的管理插件&#xff08;图…