图像处理之边缘检测(C++)

图像处理之边缘检测(C++)


文章目录

  • 图像处理之边缘检测(C++)
  • 前言
  • 一、Roberts算子
    • 1.原理
    • 2.代码实现
  • 二、Sobel算子
    • 1.原理
    • 2.代码实现
  • 三、Prewitt算子
    • 1.原理
    • 2.代码实现
  • 四、Laplacian算子
    • 1.原理
    • 2.代码实现
  • 五、LOG算子
    • 1.原理
    • 2.代码实现
  • 六、DOG算子
    • 1.原理
    • 2.代码实现
  • 总结


前言

边缘检测是图像处理的基础,边缘检测主要是为了找到图像中亮度变化剧烈的像素点构成的集合,即图像的轮廓(边缘)。
传统边缘检测的主要有Roberts、Sobel、Prewitt、Laplacian、LOG、DOG等方法,本文介绍上述的边缘检测算子的实现。
原图:
原图


一、Roberts算子

1.原理

Roberts算子是一种斜向偏差分的梯度计算方法,采用对角方向相邻的两像素值之差,梯度的大小代表边缘的强度,梯度的方向与边缘的走向垂直。它是2X2算子模板。2个卷积核形成了Roberts算子。图像中的每一个点都用这2个核做卷积。
卷积核形式如下:
卷积核形式
计算公式如下
计算梯度
计算梯度值
备注:采用绝对值相加减少计算量。

2.代码实现

#include <opencv.hpp>
#include <iostream>/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
*/
void roberts(const cv::Mat& src, cv::Mat& dst)
{// 创建卷积核cv::Mat kernel_x = (cv::Mat_<float>(2, 2) << 1, 0, 0, -1);cv::Mat kernel_y = (cv::Mat_<float>(2, 2) << 0, 1, -1, 0);// 卷积计算// 卷积核翻转cv::flip(kernel_x, kernel_x, -1);cv::flip(kernel_y, kernel_y, -1);// 相关性计算cv::Mat dst_x, dst_y;cv::filter2D(src, dst_x, kernel_x.depth(), kernel_x);cv::filter2D(src, dst_y, kernel_y.depth(), kernel_y);// 绝对值转换cv::convertScaleAbs(dst_x, dst_x);cv::convertScaleAbs(dst_y, dst_y);// 计算梯度dst = dst_x + dst_y;cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX,CV_8UC1);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;roberts(src, dst);// 保存图片cv::imwrite("dst.jpg", dst);system("pause");return 0;
}

在这里插入图片描述

二、Sobel算子

1.原理

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。它结合高斯平滑和微分求导,用来计算图像灰度函数的近似梯度(读者可以尝试分离卷积核,即可看出卷积核是由一个求解水平梯度或者垂直梯度的卷积核和非归一化的高斯平滑相乘得到)。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。它对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。

卷积核形式:
卷积核
计算公式如下:
卷积
幅值
在这里插入图片描述

2.代码实现

/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief sobel算子实现
*/
void sobel(const cv::Mat& src, cv::Mat& dst) {// 创建卷积核cv::Mat kernel_x = (cv::Mat_<float>(3,3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);cv::Mat kernel_y = (cv::Mat_<float>(3, 3) << 1, 2, 1, 0, 0, 0, -1, -2, -1);// 卷积运算// 翻转卷积核cv::flip(kernel_x, kernel_x, -1);cv::flip(kernel_y, kernel_y, -1);// 相关性计算cv::Mat dst_x, dst_y;cv::filter2D(src, dst_x, kernel_x.depth(), kernel_x);cv::filter2D(src, dst_y, kernel_y.depth(), kernel_y);cv::convertScaleAbs(dst_x, dst_x);cv::convertScaleAbs(dst_y, dst_y);cv::normalize(dst_x + dst_y, dst, 0, 255, cv::NORM_MINMAX, CV_8U);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;sobel(src, dst);// 保存图片cv::imwrite("dst.jpg", dst);system("pause");return 0;
}

结果

三、Prewitt算子

1.原理

Prewitt算子的计算步骤如sobel算子,将方向的差分运算和局部平均相结合的方法(通过分离卷积核即可得出结论,不多赘述),也是取水平和垂直两个卷积核来分别对图像中各个像素点做卷积运算,所不同的是,Sobel 算子是先做加权平均然后再微分,Prewitt 算子是先平均后求微分。由于采用了局部灰度平均,容易检测出伪边缘,且边缘定位精度较低。
卷积核形式:
在这里插入图片描述
计算公式:
幅值

2.代码实现

/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief prewitt算子实现
*/
void prewitt(const cv::Mat& src, cv::Mat& dst) {// 创建卷积核cv::Mat kernel_x = (cv::Mat_<float>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);cv::Mat kernel_y = (cv::Mat_<float>(3, 3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);// 卷积运算// 翻转卷积核cv::flip(kernel_x, kernel_x, -1);cv::flip(kernel_y, kernel_y, -1);// 相关性计算cv::Mat dst_x, dst_y;cv::filter2D(src, dst_x, kernel_x.depth(), kernel_x);cv::filter2D(src, dst_y, kernel_y.depth(), kernel_y);cv::convertScaleAbs(dst_x, dst_x);cv::convertScaleAbs(dst_y, dst_y);cv::normalize(dst_x + dst_y, dst, 0, 255, cv::NORM_MINMAX, CV_8U);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;prewitt(src, dst);// 保存图片cv::imwrite("prewitt_dst.jpg", dst);system("pause");return 0;
}

prewitt

四、Laplacian算子

1.原理

它不依赖于边缘方向的二阶微分算子,对图像中的阶跃型边缘点定位准确,该算子对噪声非常敏感,它使噪声成分得到加强,这两个特性使得该算子容易丢失一部分边缘的方向信息,造成一些不连续的检测边缘,同时抗噪声能力比较差,由于其算法可能会出现双像素边界,常用来判断边缘像素位于图像的明区或暗区。

卷积核

2.代码实现

/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief prewitt算子实现
*/
void laplacian(const cv::Mat& src, cv::Mat& dst) {// 创建卷积核//cv::Mat kernel = (cv::Mat_<float>(3, 3) << 0, 1, 0, 1, -4, 1, 0, 1, 0);cv::Mat kernel = (cv::Mat_<float>(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1);// 卷积运算// 翻转卷积核cv::flip(kernel, kernel, -1);// 相关性计算cv::filter2D(src, dst, kernel.depth(), kernel);cv::convertScaleAbs(dst, dst);cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX, CV_8U);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;laplacian(src, dst);// 保存图片cv::imwrite("laplacian.jpg", dst);system("pause");return 0;
}

result

五、LOG算子

1.原理

高斯拉普拉斯算子Lapacian of gaussian先对图像进行高斯平滑滤波处理,然后再与Laplacian算子进行卷积。其处理过程:灰度-高斯-拉普拉斯-负值为0。
LOG

2.代码实现

/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief LOG算子实现
*/
void LOG(const cv::Mat& src, cv::Mat& dst) {// 创建卷积核cv::Mat kernel = (cv::Mat_<float>(5, 5) << 0, 0, -1, 0, 0,0, -1, -2, -1, 0,-1, -2, 16, -2, -1,0, -1, -2, -1, 0,0, 0, -1, 0, 0);// 卷积运算(卷积核对称无需翻转)cv::filter2D(src, dst, kernel.depth(), kernel);cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY);dst.convertTo(dst, CV_8U);
}/*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief LOG算子实现
*/
void LOG1(const cv::Mat& src, cv::Mat& dst) {// 高斯滤波cv::GaussianBlur(src, dst, cv::Size(5, 5),0.5);// laplacianlaplacian(dst, dst);cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY);dst.convertTo(dst, CV_8U);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;LOG(src, dst);// 保存图片cv::imwrite("LOG.jpg", dst);system("pause");return 0;
}

LOG

六、DOG算子

1.原理

Difference of Gaussian(DOG)是高斯函数的差分。它是可以通过将图像与高斯函数进行卷积得到一幅图像的低通滤波结果,它对高斯拉普拉斯LoG的近似,在某一尺度上的特征检测可以通过对两个相邻高斯尺度空间的图像相减,得到DoG的响应值图像。
公式证明:
证明
计算步骤:
使用两个不同标准差的高斯核平滑图像,然后结果相减,负值为0,获得边缘检测结果。

2.代码实现

*
* @param const cv::Mat& src		输入图像
* @param cv::Mat& dst			输出图像
* @brief DOG算子实现
*/
void DOG(const cv::Mat& src, cv::Mat& dst,double sigma,int k) {cv::Mat dst_x, dst_y;cv::GaussianBlur(src, dst_x, cv::Size(3, 3), sigma);cv::GaussianBlur(src, dst_y, cv::Size(3, 3), k*sigma);dst = dst_x - dst_y;cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY);dst.convertTo(dst, CV_8U);
}int main()
{// 读取图片std::string filepath = "F://work_study//algorithm_demo//regionGrow_test.jpg";cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);if (src.empty()){return -1;}cv::Mat dst;DOG(src, dst,1,2);// 保存图片cv::imwrite("DOG.jpg", dst);system("pause");return 0;
}

DOG


总结

本文介绍了图像处理中的边缘检测算法,包括了Roberts、Sobel、Prewitt、laplacian、DOG、LOG等算子的C++实现和原理介绍,欢迎大家指出问题和交流讨论。

参考资料:
高斯滤波(Gauss filtering)
图像处理 | 最常用的边缘检测详解与代码(Robert, Sober, Prewitt, Canny, Kirsch, Laplacian, LOG, DOG算子)
LOG算子实现

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

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

相关文章

完全匹配企业需求的替代FTP升级软件怎么找

企业在处理数据传输时&#xff0c;效率和安全性是关键。尽管传统的FTP曾被广泛采用&#xff0c;但因其传输慢、安全性不足和难以管理等问题&#xff0c;已不再满足现代企业的需求。许多企业正在寻找能够满足其需求的FTP替代方案&#xff0c;但市场上选择众多&#xff0c;找到合…

Python01:初入Python(Mac)

Python环境准备 下载Python&#xff1a;官网https://www.python.org/ 下载PyCharm&#xff1a;官网https://www.jetbrains.com/pycharm/download Python与PyCharm的关系 Python&#xff08;解释器&#xff09;&#xff1a;机器语言—>翻译人员–>翻译成电脑能读懂的 PyC…

STM32应用开发进阶--SPI总线(7脚OLED中景园ss1306+HAL库_硬件SPI/软件模拟SPI)

实现目标 1、掌握SPI总线基础知识&#xff1b; 2、会使用软件模拟SPI总线和STM32硬件SPI总线&#xff1b; 3、 学会STM32CubeMX软件关于SPI的配置; 4、掌握OLED显示屏驱动&#xff1b; 5、具体目标&#xff1a;&#xff08;1&#xff09;用STM32硬件SPI驱动OLED显示“你好…

抽烟行为检测:从传统巡查到智能算法

在当前人工智能和计算机视觉技术的迅猛发展下&#xff0c;基于视觉分析的抽烟行为检测算法成为一种高效的技术手段。此类算法通常依赖于深度学习模型&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;通过对摄像头捕捉的视频流进行实时分析&#xff0c;能…

在旧版 Nginx 官方 Dockerfile 上集成第三方模块的探索

问题背景 线上生产环境用的 nginx 1.21, 然后由于新功能引入的一个问题&#xff0c;需要使用第三方模块 ngx_http_subs_filter_module&#xff0c;目的是使用正则表达式来移除响应结果中的某些数据。 由于这个客户的环境非常重要&#xff0c;组内的大哥们也不敢随便升级 ngin…

网络安全、信息安全、数据安全的定义与区别

信息安全 信息安全是指信息的保密性、完整性、可用性和真实性的保持。从定义角度来说&#xff0c;信息安全没有严格标准定义&#xff0c;但从信息安全涉及的内容出发&#xff0c;信息安全确保信息存储或传输中的信息&#xff0c;不被他人有意或无意的窃取与破坏。这里的“信息”…

Vue3+ts(day07:pinia)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

ENVI光谱识别指导采矿管理者监测铜矿分布

圣地亚哥SRGIS的GIS专家Chile需要利用影像光谱信号勘察Chuquicamata的铜矿分布。 解决方案 Chuquicamata是世界上最大的斑岩铜矿分布区。SRGIS发现西部地区只有有限的矿物和贫瘠的岩石&#xff0c;但东部有铜矿分布。为了进一步测定矿藏的情况&#xff0c;他们开发出一套程序&a…

NoSQL Redis配置与优化

一、关系数据库与非关系型数据库 1. 关系型数据库&#xff1a; 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上&#xff0c;一般面向于记录。 SQL 语句&#xff08;标准数据查询语言&#xff09;就是一种基于关系型…

redis核心面试题一(架构原理+RDB+AOF)

文章目录 0. redis与mysql区别1. redis是单线程架构还是多线程架构2. redis单线程为什么这么快3. redis过期key删除策略4. redis主从复制架构原理5. redis哨兵模式架构原理6. redis高可用集群架构原理7. redis持久化之RDB8. redis持久化之AOF9. redis持久化之混合持久化 0. red…

穷人如何翻身赚钱?不妨试试这5个冷门生意,干好了,收入相当不错

根据统计数据&#xff0c;我国月收入超过3000元的人口已超过4亿&#xff0c;这意味着仍有约10亿人的月收入低于3000元。正因为如此&#xff0c;网络上许多人都自嘲为“穷人”。 然而&#xff0c;穷人真的无法改变自己的命运吗&#xff1f;并非如此。对于渴望赚钱的穷人来说&am…

传统蓝牙模块BR/EDR与低功耗蓝牙模块有什么区别?

传统蓝牙模块BR/EDR与低功耗蓝牙模块有什么区别&#xff1f;下面跟随美迅物联网MesoonRF从多个维度来了解。   概述&#xff1a;低功耗蓝牙采用了高斯频移键控&#xff08;GFSK&#xff09;。这里我们先抛开蓝牙的协议&#xff0c;单纯从Radio的角度看收发通信&#xff0c;Ra…

【Crypto】Url编码

文章目录 Url编码解题感悟 Url编码 Url编码 搞定 小小flag&#xff0c;拿下&#xff01; 解题感悟 有点饿了…

图数据库助力供应链柔性升级

导读 当今市场环境受短视频等流媒体影响&#xff0c;任何风险事件在社交网络中传播速度极其迅速&#xff0c;留给企业的反应时间按分秒计&#xff0c;传统供应链的年度计划面对剧烈变化的市场环境已失去意义。此外&#xff0c;受近年局势动荡的影响&#xff0c;市场需求和供应…

APISIX-简单使用

APISIX-简单使用 这个工具还是很不错的&#xff0c;可视化的配置很清晰 &#xff0c; 想用NGINX的配置模式也是可以的&#xff0c;就是要去修改配置文件了。 APISIX&#xff0c;一个很不错的可视化工具&#xff0c;用来代替Nginx相当不错&#xff0c;可作为Nginx的平替方案&…

【Python进阶】主流电商平台数据分析||数据采集返回商品详情主题链接主图SKU数据

Python是一种高级编程语言&#xff0c;广泛应用于软件开发、数据分析、人工智能、科学计算等领域。在软件开发方面&#xff0c;Python在网站开发、网络编程、桌面软件开发等方面有着广泛的应用。在数据分析和人工智能领域&#xff0c;Python的各种库如NumPy、Pandas、Matplotli…

守护者:ThingsBoard物联网网关在温室环境监测中的应用

系统设计 智慧农业温室大棚系统由传感器及执行设备、数据传输网关、智慧农业温室大棚管理平台组成。 系统支持实时采集温室大棚内的空气温湿度、土壤温湿度、光照和二氧化碳等环境参数&#xff0c;根据农作物的生长需求自动控制温室中电器设备的启停&#xff0c;从而达到植物生…

【Linux】信号集及信号集操作函数

文章目录 一、信号集是什么&#xff1f;二、信号集操作函数1. sigemptyset2. sigfillset3. sigaddset4. sigdelset5. sigismember6. sigprocmask (仅用于读取或更改block表)7. sigpending (仅用于读取pending表) 一、信号集是什么&#xff1f; 对于每个进程, 都有三个信号集, …

k8s集群部署成功后某个节点突然出现notready状态解决办法

通过&#xff1a; kubectl get nodes 查看master1节点为not ready 通过查看日志&#xff1a; journalctl -f -u kubelet.service 看到这里 查看状态&#xff1a; systemctl status kubelet.service 重启一样会报错 执行&#xff1a; swapoff -a 执行后&#xff0c;重启…

pytorch深度学习-环境搭建

1.Anaconda下载&#xff08;首先安装Anaconda不需要先安装Python了&#xff01;&#xff09; 版本 3.11. Download Anaconda Distribution | Anaconda 1.2 跳过注册直接下载 2.安装 直接next, (Install for 可以选择All Users&#xff0c;我选择的是All Users) 点击默认选项…